|
|
1.1 root 1: /* $Id: qwknodes.c,v 1.16 2005/12/04 20:41:51 rswindell Exp $ */
2:
3: /* Synchronet QWKnet node list or route.dat file generator */
4:
5: /****************************************************************************
6: * @format.tab-size 4 (Plain Text/Source Code File Header) *
7: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
8: * *
9: * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html *
10: * *
11: * This program is free software; you can redistribute it and/or *
12: * modify it under the terms of the GNU General Public License *
13: * as published by the Free Software Foundation; either version 2 *
14: * of the License, or (at your option) any later version. *
15: * See the GNU General Public License for more details: gpl.txt or *
16: * http://www.fsf.org/copyleft/gpl.html *
17: * *
18: * Anonymous FTP access to the most recent released source is available at *
19: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
20: * *
21: * Anonymous CVS access to the development source and modification history *
22: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
23: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
24: * (just hit return, no password is necessary) *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
26: * *
27: * For Synchronet coding style and modification guidelines, see *
28: * http://www.synchro.net/source.html *
29: * *
30: * You are encouraged to submit any modifications (preferably in Unix diff *
31: * format) via e-mail to [email protected] *
32: * *
33: * Note: If this box doesn't appear square, then you need to fix your tabs. *
34: ****************************************************************************/
35:
36: #include "sbbs.h"
37: #include "nopen.h"
38: #include "crc16.h"
39: #include "crc32.h"
40: #include "conwrap.h" /* kbhit */
41:
42: unsigned _stklen=10000;
43: smb_t smb;
44: scfg_t cfg;
45:
46: void stripctrla(uchar *str)
47: {
48: uchar out[256];
49: int i,j;
50:
51: for(i=j=0;str[i] && j<sizeof(out)-1;i++) {
52: if(str[i]==CTRL_A && str[i+1]!=0)
53: i++;
54: else
55: out[j++]=str[i];
56: }
57: out[j]=0;
58: strcpy(str,out);
59: }
60:
61: int lputs(char* str)
62: {
63: char tmp[256];
64: int i,j,k;
65:
66: j=strlen(str);
67: for(i=k=0;i<j;i++) /* remove CRs */
68: if(str[i]==CR && str[i+1]==LF)
69: continue;
70: else
71: tmp[k++]=str[i];
72: tmp[k]=0;
73: return(fputs(tmp,stderr));
74: }
75: /****************************************************************************/
76: /* Performs printf() through local assembly routines */
77: /* Called from everywhere */
78: /****************************************************************************/
79: int lprintf(char *fmat, ...)
80: {
81: va_list argptr;
82: char sbuf[256];
83: int chcount;
84:
85: va_start(argptr,fmat);
86: chcount=vsnprintf(sbuf,sizeof(sbuf),fmat,argptr);
87: sbuf[sizeof(sbuf)-1]=0;
88: va_end(argptr);
89: lputs(sbuf);
90: return(chcount);
91: }
92: void bail(int code)
93: {
94: exit(code);
95: }
96:
97: char *loadmsgtail(smbmsg_t msg)
98: {
99: char *buf=NULL;
100: ushort xlat;
101: int i;
102: long l=0,length;
103:
104: for(i=0;i<msg.hdr.total_dfields;i++) {
105: if(msg.dfield[i].type!=TEXT_TAIL)
106: continue;
107: fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
108: ,SEEK_SET);
109: fread(&xlat,2,1,smb.sdt_fp);
110: if(xlat!=XLAT_NONE) /* no translations supported */
111: continue;
112: length=msg.dfield[i].length-2;
113: if((buf=realloc(buf,l+msg.dfield[i].length+1))==NULL)
114: return(buf);
115: l+=fread(buf+l,1,length,smb.sdt_fp);
116: buf[l]=0;
117: }
118: return(buf);
119: }
120:
121:
122: void gettag(smbmsg_t msg, char *tag)
123: {
124: char *buf,*p;
125:
126: tag[0]=0;
127: buf=loadmsgtail(msg);
128: if(buf==NULL)
129: return;
130: truncsp(buf);
131: stripctrla(buf);
132: p=strrchr(buf,LF);
133: if(!p) p=buf;
134: else p++;
135: if(!strnicmp(p," � Synchronet � ",16))
136: p+=16;
137: if(!strnicmp(p," * Synchronet * ",16))
138: p+=16;
139: while(*p && *p<=' ') p++;
140: strcpy(tag,p);
141: free(buf);
142: }
143:
144:
145: #define FEED (1<<0)
146: #define LOCAL (1<<1)
147: #define APPEND (1<<2)
148: #define TAGS (1<<3)
149:
150: #define ROUTE (1<<1)
151: #define NODES (1<<2)
152: #define USERS (1<<3)
153:
154: char *usage="\nusage: qwknodes [-opts] cmds"
155: "\n"
156: "\n cmds: r = create route.dat"
157: "\n u = create users.dat"
158: "\n n = create nodes.dat"
159: "\n"
160: "\n opts: f = format addresses for nodes that feed from this system"
161: "\n a = append existing output files"
162: "\n t = include tag lines in nodes.dat"
163: "\n l = include local users in users.dat"
164: "\n m# = maximum message age set to # days"
165: "\n";
166:
167: int main(int argc, char **argv)
168: {
169: char str[256],tmp[128],tag[256],addr[256],*p;
170: int i,j,mode=0,cmd=0,o_mode,max_age=0;
171: ushort smm,sbl;
172: ulong *crc=NULL,curcrc,total_crcs=0,l;
173: FILE *route,*users,*nodes;
174: time_t now;
175: smbmsg_t msg;
176: char *ctrl_dir;
177: char revision[16];
178:
179: sscanf("$Revision: 1.16 $", "%*s %s", revision);
180:
181: fprintf(stderr,"\nSynchronet QWKnet Node/Route/User List Generator v%s-%s\n"
182: ,revision, PLATFORM_DESC);
183:
184: for(i=1;i<argc;i++)
185: for(j=0;argv[i][j];j++)
186: switch(toupper(argv[i][j])) {
187: case '/':
188: case '-':
189: while(argv[i][++j])
190: switch(toupper(argv[i][j])) {
191: case 'F':
192: mode|=FEED;
193: break;
194: case 'L':
195: mode|=LOCAL;
196: break;
197: case 'A':
198: mode|=APPEND;
199: break;
200: case 'T':
201: mode|=TAGS;
202: break;
203: case 'M':
204: j++;
205: max_age=atoi(argv[i]+j);
206: while(isdigit(argv[i][j+1])) j++;
207: break;
208: default:
209: printf(usage);
210: return(1);
211: }
212: j--;
213: break;
214: case 'R':
215: cmd|=ROUTE;
216: break;
217: case 'U':
218: cmd|=USERS;
219: break;
220: case 'N':
221: cmd|=NODES;
222: break;
223: default:
224: printf(usage);
225: return(1);
226: }
227:
228: if(!cmd) {
229: printf(usage);
230: return(1);
231: }
232:
233: if(mode&APPEND)
234: o_mode=O_WRONLY|O_CREAT|O_APPEND;
235: else
236: o_mode=O_WRONLY|O_CREAT|O_TRUNC;
237:
238: if(cmd&NODES)
239: if((nodes=fnopen(&i,"nodes.dat",o_mode))==NULL) {
240: printf("\7\nError opening nodes.dat\n");
241: return(1);
242: }
243:
244: if(cmd&USERS)
245: if((users=fnopen(&i,"users.dat",o_mode))==NULL) {
246: printf("\7\nError opening users.dat\n");
247: return(1);
248: }
249:
250: if(cmd&ROUTE)
251: if((route=fnopen(&i,"route.dat",o_mode))==NULL) {
252: printf("\7\nError opening route.dat\n");
253: return(1);
254: }
255:
256: cfg.size=sizeof(cfg);
257: ctrl_dir=getenv("SBBSCTRL");
258: if(ctrl_dir==NULL || ctrl_dir[0]==0) {
259: ctrl_dir="/sbbs/ctrl"; /* Not set? Use default */
260: printf("!SBBSCTRL environment variable not set, using default value: %s\n\n"
261: ,ctrl_dir);
262: }
263: SAFECOPY(cfg.ctrl_dir, ctrl_dir);
264:
265: if(!load_cfg(&cfg, NULL, TRUE, str)) {
266: printf("\7\n%s\n",str);
267: }
268:
269: now=time(NULL);
270: smm=crc16("smm",0);
271: sbl=crc16("sbl",0);
272: fprintf(stderr,"\n\n");
273: for(i=0;i<cfg.total_subs;i++) {
274: if(!(cfg.sub[i]->misc&SUB_QNET))
275: continue;
276: fprintf(stderr,"%-*s %s\n"
277: ,LEN_GSNAME,cfg.grp[cfg.sub[i]->grp]->sname,cfg.sub[i]->lname);
278: sprintf(smb.file,"%s%s",cfg.sub[i]->data_dir,cfg.sub[i]->code);
279: smb.retry_time=30;
280: smb.subnum=i;
281: if((j=smb_open(&smb))!=0) {
282: printf("smb_open returned %d\n",j);
283: continue;
284: }
285: if((j=smb_locksmbhdr(&smb))!=0) {
286: printf("smb_locksmbhdr returned %d\n",j);
287: smb_close(&smb);
288: continue;
289: }
290: if((j=smb_getstatus(&smb))!=0) {
291: printf("smb_getstatus returned %d\n",j);
292: smb_close(&smb);
293: continue;
294: }
295: smb_unlocksmbhdr(&smb);
296: msg.offset=smb.status.total_msgs;
297: if(!msg.offset) {
298: smb_close(&smb);
299: printf("Empty.\n");
300: continue;
301: }
302: while(!kbhit() && !ferror(smb.sid_fp) && msg.offset) {
303: msg.offset--;
304: fseek(smb.sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
305: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
306: break;
307: fprintf(stderr,"%-5lu\r",msg.offset+1);
308: if(msg.idx.to==smm || msg.idx.to==sbl)
309: continue;
310: if(max_age && now-msg.idx.time>((ulong)max_age*24UL*60UL*60UL))
311: continue;
312: if((j=smb_lockmsghdr(&smb,&msg))!=0) {
313: printf("smb_lockmsghdr returned %d\n",j);
314: break;
315: }
316: if((j=smb_getmsghdr(&smb,&msg))!=0) {
317: printf("smb_getmsghdr returned %d\n",j);
318: break;
319: }
320: smb_unlockmsghdr(&smb,&msg);
321: if((mode&LOCAL && msg.from_net.type==NET_NONE)
322: || msg.from_net.type==NET_QWK) {
323: if(msg.from_net.type!=NET_QWK)
324: msg.from_net.addr="";
325: if(cmd&USERS) {
326: sprintf(str,"%s%s",msg.from_net.addr,msg.from);
327: curcrc=crc32(str,0);
328: }
329: else
330: curcrc=crc32(msg.from_net.addr,0);
331: for(l=0;l<total_crcs;l++)
332: if(curcrc==crc[l])
333: break;
334: if(l==total_crcs) {
335: total_crcs++;
336: if((crc=(ulong *)realloc(crc
337: ,sizeof(ulong)*total_crcs))==NULL) {
338: printf("Error allocating %lu bytes\n"
339: ,sizeof(ulong)*total_crcs);
340: break;
341: }
342: crc[l]=curcrc;
343: if(cmd&ROUTE && msg.from_net.type==NET_QWK) {
344: strcpy(addr,msg.from_net.addr);
345: if(mode&FEED) {
346: p=strrchr(addr,'/');
347: if(!p)
348: p=addr;
349: else
350: *(p++)=0;
351: sprintf(str,"%s %s:%s%c%s"
352: ,unixtodstr(&cfg,msg.hdr.when_written.time,tmp)
353: ,p,cfg.sys_id,p==addr ? 0 : '/'
354: ,addr);
355: fprintf(route,"%s\r\n",str);
356: }
357: else {
358: p=strrchr(addr,'/');
359: if(p) {
360: *(p++)=0;
361: fprintf(route,"%s %s:%.*s\r\n"
362: ,unixtodstr(&cfg,msg.hdr.when_written.time,str)
363: ,p
364: ,(uint)(p-addr)
365: ,addr);
366: }
367: }
368: }
369: if(cmd&USERS) {
370: if(msg.from_net.type!=NET_QWK)
371: strcpy(str,cfg.sys_id);
372: else if(mode&FEED)
373: sprintf(str,"%s/%s",cfg.sys_id,msg.from_net.addr);
374: else
375: strcpy(str,msg.from_net.addr);
376: p=strrchr(str,'/');
377: if(p)
378: fprintf(users,"%-25.25s %-8.8s %s (%s)\r\n"
379: ,msg.from,p+1
380: ,unixtodstr(&cfg,msg.hdr.when_written.time,tmp)
381: ,str);
382: else
383: fprintf(users,"%-25.25s %-8.8s %s\r\n"
384: ,msg.from,str
385: ,unixtodstr(&cfg,msg.hdr.when_written.time,tmp));
386: }
387: if(cmd&NODES && msg.from_net.type==NET_QWK) {
388: if(mode&TAGS)
389: gettag(msg,tag);
390: if(mode&FEED)
391: sprintf(str,"%s/%s",cfg.sys_id,msg.from_net.addr);
392: else
393: strcpy(str,msg.from_net.addr);
394: p=strrchr(str,'/');
395: if(p) {
396: if(mode&TAGS)
397: fprintf(nodes,"%-8.8s %s\r\n"
398: ,p+1
399: ,tag);
400: else
401: fprintf(nodes,"%-8.8s %s (%s)\r\n"
402: ,p+1
403: ,unixtodstr(&cfg,msg.hdr.when_written.time,tmp)
404: ,str);
405: }
406: else
407: fprintf(nodes,"%-8.8s %s\r\n"
408: ,str
409: ,mode&TAGS
410: ? tag
411: : unixtodstr(&cfg,msg.hdr.when_written.time,tmp));
412: }
413: }
414: }
415: smb_freemsgmem(&msg);
416: }
417:
418: smb_close(&smb);
419: if(kbhit()) {
420: getch();
421: fprintf(stderr,"Key pressed.\n");
422: break;
423: }
424: }
425: fprintf(stderr,"Done.\n");
426:
427: return(0);
428: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.