|
|
1.1 root 1: /* QWKNODES.C */
2:
3: /* Synchronet QWKnet node list or route.dat file generator */
4:
5: /* $Id: qwknodes.c,v 1.3 2000/11/04 12:03:51 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39: #include "crc32.h"
40:
41: unsigned _stklen=10000;
42: smb_t smb;
43: scfg_t cfg;
44:
45: /****************************************************************************/
46: /* Updates 16-bit "rcrc" with character 'ch' */
47: /****************************************************************************/
48: void ucrc16(uchar ch, ushort *rcrc) {
49: ushort i, cy;
50: uchar nch=ch;
51:
52: for (i=0; i<8; i++) {
53: cy=*rcrc & 0x8000;
54: *rcrc<<=1;
55: if (nch & 0x80) *rcrc |= 1;
56: nch<<=1;
57: if (cy) *rcrc ^= 0x1021; }
58: }
59:
60: /****************************************************************************/
61: /* Returns 16-crc of string (not counting terminating NULL) */
62: /****************************************************************************/
63: ushort crc16(char *str)
64: {
65: int i=0;
66: ushort crc=0;
67:
68: ucrc16(0,&crc);
69: while(str[i])
70: ucrc16(str[i++],&crc);
71: ucrc16(0,&crc);
72: ucrc16(0,&crc);
73: return(crc);
74: }
75:
76: /****************************************************************************/
77: /* Returns 32-crc of string (not counting terminating NULL) */
78: /****************************************************************************/
79: ulong _crc32(char *str)
80: {
81: int i=0;
82: ulong crc=0xffffffffUL;
83:
84: while(str[i])
85: crc=ucrc32(str[i++],crc);
86: crc=~crc;
87: return(crc);
88: }
89:
90: #if 0
91: /****************************************************************************/
92: /* Converts unix time format (long - time_t) into a char str MM/DD/YY */
93: /****************************************************************************/
94: char *unixtodstr(time_t unix, char *str)
95: {
96: struct date date;
97: struct time curtime;
98:
99: if(!unix)
100: strcpy(str,"00/00/00");
101: else {
102: unixtodos(unix,&date,&curtime);
103: if((unsigned)date.da_mon>12) { /* DOS leap year bug */
104: date.da_mon=1;
105: date.da_year++; }
106: if((unsigned)date.da_day>31)
107: date.da_day=1;
108: if(sys_misc&SM_EURODATE)
109: sprintf(str,"%02u/%02u/%02u",date.da_day,date.da_mon
110: ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900);
111: else
112: sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
113: ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
114: return(str);
115: }
116: #else
117: /****************************************************************************/
118: /* Converts unix time format (long - time_t) into a char str MM/DD/YY */
119: /****************************************************************************/
120: char * unixtodstr(time_t unix, char *str)
121: {
122: struct tm* tm;
123:
124: if(!unix)
125: strcpy(str,"00/00/00");
126: else {
127: tm=gmtime(&unix);
128: if(tm==NULL) {
129: strcpy(str,"00/00/00");
130: return(str);
131: }
132: if(tm->tm_mon>11) { /* DOS leap year bug */
133: tm->tm_mon=0;
134: tm->tm_year++; }
135: if(tm->tm_mday>31)
136: tm->tm_mday=1;
137: if(cfg.sys_misc&SM_EURODATE)
138: sprintf(str,"%02u/%02u/%02u",tm->tm_mday,tm->tm_mon+1
139: ,TM_YEAR(tm->tm_year));
140: else
141: sprintf(str,"%02u/%02u/%02u",tm->tm_mon+1,tm->tm_mday
142: ,TM_YEAR(tm->tm_year)); }
143: return(str);
144: }
145: #endif
146:
147: /****************************************************************************/
148: /* Puts a backslash on path strings */
149: /****************************************************************************/
150: void backslash(char *str)
151: {
152: int i;
153:
154: i=strlen(str);
155: if(i && str[i-1]!='\\') {
156: str[i]='\\'; str[i+1]=0; }
157: }
158: /****************************************************************************/
159: /* Network open function. Opens all files DENYALL and retries LOOP_NOPEN */
160: /* number of times if the attempted file is already open or denying access */
161: /* for some other reason. All files are opened in BINARY mode. */
162: /****************************************************************************/
163: int nopen(char *str, int access)
164: {
165: int file,share,count=0;
166:
167: if(access==O_RDONLY) share=SH_DENYWR;
168: else share=SH_DENYRW;
169: while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
170: && errno==EACCES && count++<LOOP_NOPEN);
171: if(file==-1 && errno==EACCES)
172: lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
173: return(file);
174: }
175: /****************************************************************************/
176: /* This function performs an nopen, but returns a file stream with a buffer */
177: /* allocated. */
178: /****************************************************************************/
179: FILE *fnopen(int *file, char *str, int access)
180: {
181: char mode[128];
182: FILE *stream;
183:
184: if(((*file)=nopen(str,access))==-1)
185: return(NULL);
186:
187: if(access&O_APPEND) {
188: if(access&O_RDONLY)
189: strcpy(mode,"a+");
190: else
191: strcpy(mode,"a"); }
192: else {
193: if(access&O_WRONLY)
194: strcpy(mode,"r+");
195: else
196: strcpy(mode,"r"); }
197: stream=fdopen((*file),mode);
198: if(stream==NULL) {
199: close(*file);
200: return(NULL); }
201: setvbuf(stream,NULL,_IOFBF,16*1024);
202: return(stream);
203: }
204:
205: /****************************************************************************/
206: /* Truncates white-space chars off end of 'str' and terminates at first tab */
207: /****************************************************************************/
208: void truncsp(char *str)
209: {
210: uchar c;
211:
212: c=strlen(str);
213: while(c && (uchar)str[c-1]<=SP) c--;
214: str[c]=0;
215: }
216:
217: void stripctrla(uchar *str)
218: {
219: uchar out[256];
220: int i,j;
221:
222: for(i=j=0;str[i];i++) {
223: if(str[i]==1)
224: i++;
225: else
226: out[j++]=str[i]; }
227: out[j]=0;
228: strcpy(str,out);
229: }
230:
231:
232: long lputs(char FAR16 *str)
233: {
234: char tmp[256];
235: int i,j,k;
236:
237: j=strlen(str);
238: for(i=k=0;i<j;i++) /* remove CRs */
239: if(str[i]==CR && str[i+1]==LF)
240: continue;
241: else
242: tmp[k++]=str[i];
243: tmp[k]=0;
244: return(fputs(tmp,stderr));
245: }
246: /****************************************************************************/
247: /* Performs printf() through local assembly routines */
248: /* Called from everywhere */
249: /****************************************************************************/
250: int lprintf(char *fmat, ...)
251: {
252: va_list argptr;
253: char sbuf[256];
254: int chcount;
255:
256: va_start(argptr,fmat);
257: chcount=vsprintf(sbuf,fmat,argptr);
258: va_end(argptr);
259: lputs(sbuf);
260: return(chcount);
261: }
262: void bail(int code)
263: {
264: exit(code);
265: }
266:
267:
268: char *loadmsgtail(smbmsg_t msg)
269: {
270: char *buf=NULL;
271: ushort xlat;
272: int i;
273: long l=0,length;
274:
275: for(i=0;i<msg.hdr.total_dfields;i++) {
276: if(msg.dfield[i].type!=TEXT_TAIL)
277: continue;
278: fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
279: ,SEEK_SET);
280: fread(&xlat,2,1,smb.sdt_fp);
281: if(xlat!=XLAT_NONE) /* no translations supported */
282: continue;
283: length=msg.dfield[i].length-2;
284: if((buf=REALLOC(buf,l+msg.dfield[i].length+1))==NULL)
285: return(buf);
286: l+=fread(buf+l,1,length,smb.sdt_fp);
287: buf[l]=0; }
288: return(buf);
289: }
290:
291:
292: void gettag(smbmsg_t msg, char *tag)
293: {
294: char *buf,*p;
295:
296: tag[0]=0;
297: buf=loadmsgtail(msg);
298: if(buf==NULL)
299: return;
300: truncsp(buf);
301: stripctrla(buf);
302: p=strrchr(buf,LF);
303: if(!p) p=buf;
304: else p++;
305: if(!strnicmp(p," � Synchronet � ",16))
306: p+=16;
307: if(!strnicmp(p," * Synchronet * ",16))
308: p+=16;
309: while(*p && *p<=SP) p++;
310: strcpy(tag,p);
311: FREE(buf);
312: }
313:
314:
315: #define FEED (1<<0)
316: #define LOCAL (1<<1)
317: #define APPEND (1<<2)
318: #define TAGS (1<<3)
319:
320: #define ROUTE (1<<1)
321: #define NODES (1<<2)
322: #define USERS (1<<3)
323:
324: char *usage="\nusage: qwknodes [/opts] cmds"
325: "\n"
326: "\n cmds: r = create route.dat"
327: "\n u = create users.dat"
328: "\n n = create nodes.dat
329: "\n"
330: "\n opts: f = format addresses for nodes that feed from this system"
331: "\n a = append existing output files"
332: "\n t = include tag lines in nodes.dat
333: "\n l = include local users in users.dat
334: "\n m# = maximum message age set to # days"
335: "\n";
336:
337: void main(int argc, char **argv)
338: {
339: char str[256],tmp[128],tag[256],addr[256],*p;
340: int i,j,mode=0,cmd=0,o_mode,max_age=0;
341: ushort smm,sbl;
342: ulong *crc=NULL,curcrc,total_crcs=0,l;
343: FILE *route,*users,*nodes;
344: time_t now;
345: read_cfg_text_t txt;
346: smbmsg_t msg;
347:
348: txt.openerr="\7\r\nError opening %s for read.\r\n";
349: txt.reading="\r\nReading %s...";
350: txt.readit="\rRead %s ";
351: txt.allocerr="\7\r\nError allocating %u bytes of memory\r\n";
352: txt.error="\7\r\nERROR: Offset %lu in %s\r\n\r\n";
353:
354: fprintf(stderr,"\nSynchronet QWKnet Node/Route/User List v1.20 "
355: "Copyright 2000 Rob Swindell\n");
356:
357:
358: for(i=1;i<argc;i++)
359: for(j=0;argv[i][j];j++)
360: switch(toupper(argv[i][j])) {
361: case '/':
362: case '-':
363: while(argv[i][++j])
364: switch(toupper(argv[i][j])) {
365: case 'F':
366: mode|=FEED;
367: break;
368: case 'L':
369: mode|=LOCAL;
370: break;
371: case 'A':
372: mode|=APPEND;
373: break;
374: case 'T':
375: mode|=TAGS;
376: break;
377: case 'M':
378: j++;
379: max_age=atoi(argv[i]+j);
380: while(isdigit(argv[i][j+1])) j++;
381: break;
382: default:
383: printf(usage);
384: exit(1); }
385: j--;
386: break;
387: case 'R':
388: cmd|=ROUTE;
389: break;
390: case 'U':
391: cmd|=USERS;
392: break;
393: case 'N':
394: cmd|=NODES;
395: break;
396: default:
397: printf(usage);
398: exit(1); }
399:
400: if(!cmd) {
401: printf(usage);
402: exit(1); }
403:
404: if(mode&APPEND)
405: o_mode=O_WRONLY|O_CREAT|O_APPEND;
406: else
407: o_mode=O_WRONLY|O_CREAT|O_TRUNC;
408:
409: if(cmd&NODES)
410: if((nodes=fnopen(&i,"nodes.dat",o_mode))==NULL) {
411: printf("\7\nError opening nodes.dat\n");
412: exit(1); }
413:
414: if(cmd&USERS)
415: if((users=fnopen(&i,"users.dat",o_mode))==NULL) {
416: printf("\7\nError opening users.dat\n");
417: exit(1); }
418:
419: if(cmd&ROUTE)
420: if((route=fnopen(&i,"route.dat",o_mode))==NULL) {
421: printf("\7\nError opening route.dat\n");
422: exit(1); }
423:
424: if(!node_dir[0]) {
425: p=getenv("SBBSNODE");
426: if(p==NULL) {
427: printf("\7\nSBBSNODE environment variable not set.\n");
428: exit(1); }
429: strcpy(node_dir,p); }
430:
431: if(node_dir[strlen(node_dir)-1]!='\\')
432: strcat(node_dir,"\\");
433:
434: read_node_cfg(&cfg,txt);
435: if(ctrl_dir[0]=='.') { /* Relative path */
436: strcpy(str,ctrl_dir);
437: sprintf(ctrl_dir,"%s%s",node_dir,str);
438: if(_fullpath(str,ctrl_dir,40))
439: strcpy(ctrl_dir,str); }
440: backslash(ctrl_dir);
441:
442: read_main_cfg(&cfg,txt);
443: if(data_dir[0]=='.') { /* Relative path */
444: strcpy(str,data_dir);
445: sprintf(data_dir,"%s%s",node_dir,str);
446: if(_fullpath(str,data_dir,40))
447: strcpy(data_dir,str); }
448: backslash(data_dir);
449: read_msgs_cfg(txt);
450:
451: now=time(NULL);
452: smm=crc16("smm");
453: sbl=crc16("sbl");
454: fprintf(stderr,"\n\n");
455: for(i=0;i<total_subs;i++) {
456: if(!(sub[i]->misc&SUB_QNET))
457: continue;
458: fprintf(stderr,"%-*s %s\n"
459: ,LEN_GSNAME,grp[sub[i]->grp]->sname,sub[i]->lname);
460: sprintf(smb.file,"%s%s",sub[i]->data_dir,sub[i]->code);
461: smb.retry_time=30;
462: if((j=smb_open(&smb))!=0) {
463: printf("smb_open returned %d\n",j);
464: continue; }
465: if((j=smb_locksmbhdr(&smb))!=0) {
466: printf("smb_locksmbhdr returned %d\n",j);
467: smb_close(&smb);
468: continue; }
469: if((j=smb_getstatus(&smb))!=0) {
470: printf("smb_getstatus returned %d\n",j);
471: smb_close(&smb);
472: continue; }
473: smb_unlocksmbhdr(&smb);
474: msg.offset=smb.status.total_msgs;
475: if(!msg.offset) {
476: smb_close(&smb);
477: printf("Empty.\n");
478: continue; }
479: while(!kbhit() && !ferror(smb.sid_fp) && msg.offset) {
480: msg.offset--;
481: fseek(smb.sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
482: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
483: break;
484: fprintf(stderr,"%-5lu\r",msg.offset+1);
485: if(msg.idx.to==smm || msg.idx.to==sbl)
486: continue;
487: if(max_age && now-msg.idx.time>((ulong)max_age*24UL*60UL*60UL))
488: continue;
489: if((j=smb_lockmsghdr(&smb,&msg))!=0) {
490: printf("smb_lockmsghdr returned %d\n",j);
491: break; }
492: if((j=smb_getmsghdr(&smb,&msg))!=0) {
493: printf("smb_getmsghdr returned %d\n",j);
494: break; }
495: smb_unlockmsghdr(&smb,&msg);
496: if((mode&LOCAL && msg.from_net.type==NET_NONE)
497: || msg.from_net.type==NET_QWK) {
498: if(msg.from_net.type!=NET_QWK)
499: msg.from_net.addr="";
500: if(cmd&USERS) {
501: sprintf(str,"%s%s",msg.from_net.addr,msg.from);
502: curcrc=crc32(str); }
503: else
504: curcrc=crc32(msg.from_net.addr);
505: for(l=0;l<total_crcs;l++)
506: if(curcrc==crc[l])
507: break;
508: if(l==total_crcs) {
509: total_crcs++;
510: if((crc=(ulong *)REALLOC(crc
511: ,sizeof(ulong)*total_crcs))==NULL) {
512: printf("Error allocating %lu bytes\n"
513: ,sizeof(ulong)*total_crcs);
514: break; }
515: crc[l]=curcrc;
516: if(cmd&ROUTE && msg.from_net.type==NET_QWK) {
517: strcpy(addr,msg.from_net.addr);
518: if(mode&FEED) {
519: p=strrchr(addr,'/');
520: if(!p)
521: p=addr;
522: else
523: *(p++)=0;
524: sprintf(str,"%s %s:%s%c%s"
525: ,unixtodstr(msg.hdr.when_written.time,tmp)
526: ,p,sys_id,p==addr ? 0 : '/'
527: ,addr);
528: fprintf(route,"%s\r\n",str); }
529: else {
530: p=strrchr(addr,'/');
531: if(p) {
532: *(p++)=0;
533: fprintf(route,"%s %s:%.*s\r\n"
534: ,unixtodstr(msg.hdr.when_written.time,str)
535: ,p
536: ,(uint)(p-addr)
537: ,addr); } } }
538: if(cmd&USERS) {
539: if(msg.from_net.type!=NET_QWK)
540: strcpy(str,sys_id);
541: else if(mode&FEED)
542: sprintf(str,"%s/%s",sys_id,msg.from_net.addr);
543: else
544: strcpy(str,msg.from_net.addr);
545: p=strrchr(str,'/');
546: if(p)
547: fprintf(users,"%-25.25s %-8.8s %s (%s)\r\n"
548: ,msg.from,p+1
549: ,unixtodstr(msg.hdr.when_written.time,tmp)
550: ,str);
551: else
552: fprintf(users,"%-25.25s %-8.8s %s\r\n"
553: ,msg.from,str
554: ,unixtodstr(msg.hdr.when_written.time,tmp)); }
555: if(cmd&NODES && msg.from_net.type==NET_QWK) {
556: if(mode&TAGS)
557: gettag(msg,tag);
558: if(mode&FEED)
559: sprintf(str,"%s/%s",sys_id,msg.from_net.addr);
560: else
561: strcpy(str,msg.from_net.addr);
562: p=strrchr(str,'/');
563: if(p) {
564: if(mode&TAGS)
565: fprintf(nodes,"%-8.8s %s\r\n"
566: ,p+1
567: ,tag);
568: else
569: fprintf(nodes,"%-8.8s %s (%s)\r\n"
570: ,p+1
571: ,unixtodstr(msg.hdr.when_written.time,tmp)
572: ,str); }
573: else
574: fprintf(nodes,"%-8.8s %s\r\n"
575: ,str
576: ,mode&TAGS
577: ? tag
578: : unixtodstr(msg.hdr.when_written.time,tmp)); }
579: } }
580: smb_freemsgmem(&msg); }
581:
582: smb_close(&smb);
583: if(kbhit()) {
584: getch();
585: fprintf(stderr,"Key pressed.\n");
586: break; } }
587: fprintf(stderr,"Done.\n");
588: }
589:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.