|
|
1.1 root 1: /* QWKNODES.C */
2:
3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
4:
5: /* Generates QWKnet node list or ROUTE.DAT file from Synchronet message base */
6:
7: #include "sbbs.h"
8: #include "crc32.h"
9: #include "crc16.c"
10:
11: unsigned _stklen=10000;
12: smb_t smb;
13:
14: /****************************************************************************/
15: /* Returns 32-crc of string (not counting terminating NULL) */
16: /****************************************************************************/
17: ulong crc32(char *str)
18: {
19: int i=0;
20: ulong crc=0xffffffffUL;
21:
22: while(str[i])
23: crc=ucrc32(str[i++],crc);
24: crc=~crc;
25: return(crc);
26: }
27:
28: /****************************************************************************/
29: /* Converts unix time format (long - time_t) into a char str MM/DD/YY */
30: /****************************************************************************/
31: char *unixtodstr(time_t unix, char *str)
32: {
33: struct date date;
34: struct time curtime;
35:
36: if(!unix)
37: strcpy(str,"00/00/00");
38: else {
39: unixtodos(unix,&date,&curtime);
40: if((unsigned)date.da_mon>12) { /* DOS leap year bug */
41: date.da_mon=1;
42: date.da_year++; }
43: if((unsigned)date.da_day>31)
44: date.da_day=1;
45: if(sys_misc&SM_EURODATE)
46: sprintf(str,"%02u/%02u/%02u",date.da_day,date.da_mon
47: ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900);
48: else
49: sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
50: ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
51: return(str);
52: }
53:
54: /****************************************************************************/
55: /* Puts a backslash on path strings */
56: /****************************************************************************/
57: void backslash(char *str)
58: {
59: int i;
60:
61: i=strlen(str);
62: if(i && str[i-1]!='\\') {
63: str[i]='\\'; str[i+1]=0; }
64: }
65: /****************************************************************************/
66: /* Network open function. Opens all files DENYALL and retries LOOP_NOPEN */
67: /* number of times if the attempted file is already open or denying access */
68: /* for some other reason. All files are opened in BINARY mode. */
69: /****************************************************************************/
70: int nopen(char *str, int access)
71: {
72: char logstr[256];
73: int file,share,count=0;
74:
75: if(access==O_RDONLY) share=SH_DENYWR;
76: else share=SH_DENYRW;
77: while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
78: && errno==EACCES && count++<LOOP_NOPEN);
79: if(file==-1 && errno==EACCES)
80: lputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
81: return(file);
82: }
83: /****************************************************************************/
84: /* This function performs an nopen, but returns a file stream with a buffer */
85: /* allocated. */
86: /****************************************************************************/
87: FILE *fnopen(int *file, char *str, int access)
88: {
89: char mode[128];
90: FILE *stream;
91:
92: if(((*file)=nopen(str,access))==-1)
93: return(NULL);
94:
95: if(access&O_APPEND) {
96: if(access&O_RDONLY)
97: strcpy(mode,"a+");
98: else
99: strcpy(mode,"a"); }
100: else {
101: if(access&O_WRONLY)
102: strcpy(mode,"r+");
103: else
104: strcpy(mode,"r"); }
105: stream=fdopen((*file),mode);
106: if(stream==NULL) {
107: close(*file);
108: return(NULL); }
109: setvbuf(stream,NULL,_IOFBF,16*1024);
110: return(stream);
111: }
112:
113: /****************************************************************************/
114: /* Truncates white-space chars off end of 'str' and terminates at first tab */
115: /****************************************************************************/
116: void truncsp(char *str)
117: {
118: uchar c;
119:
120: c=strlen(str);
121: while(c && (uchar)str[c-1]<=SP) c--;
122: str[c]=0;
123: }
124:
125: void stripctrla(uchar *str)
126: {
127: uchar out[256];
128: int i,j;
129:
130: for(i=j=0;str[i];i++) {
131: if(str[i]==1)
132: i++;
133: else
134: out[j++]=str[i]; }
135: out[j]=0;
136: strcpy(str,out);
137: }
138:
139:
140: long lputs(char FAR16 *str)
141: {
142: char tmp[256];
143: int i,j,k;
144:
145: j=strlen(str);
146: for(i=k=0;i<j;i++) /* remove CRs */
147: if(str[i]==CR && str[i+1]==LF)
148: continue;
149: else
150: tmp[k++]=str[i];
151: tmp[k]=0;
152: return(fputs(tmp,stderr));
153: }
154: /****************************************************************************/
155: /* Performs printf() through local assembly routines */
156: /* Called from everywhere */
157: /****************************************************************************/
158: int lprintf(char *fmat, ...)
159: {
160: va_list argptr;
161: char sbuf[256];
162: int chcount;
163:
164: va_start(argptr,fmat);
165: chcount=vsprintf(sbuf,fmat,argptr);
166: va_end(argptr);
167: lputs(sbuf);
168: return(chcount);
169: }
170: void bail(int code)
171: {
172: exit(code);
173: }
174:
175:
176: char *loadmsgtail(smbmsg_t msg)
177: {
178: char *buf=NULL;
179: ushort xlat;
180: int i;
181: long l=0,length;
182:
183: for(i=0;i<msg.hdr.total_dfields;i++) {
184: if(msg.dfield[i].type!=TEXT_TAIL)
185: continue;
186: fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
187: ,SEEK_SET);
188: fread(&xlat,2,1,smb.sdt_fp);
189: if(xlat!=XLAT_NONE) /* no translations supported */
190: continue;
191: length=msg.dfield[i].length-2;
192: if((buf=REALLOC(buf,l+msg.dfield[i].length+1))==NULL)
193: return(buf);
194: l+=fread(buf+l,1,length,smb.sdt_fp);
195: buf[l]=0; }
196: return(buf);
197: }
198:
199:
200: void gettag(smbmsg_t msg, char *tag)
201: {
202: char *buf,*p;
203:
204: tag[0]=0;
205: buf=loadmsgtail(msg);
206: if(buf==NULL)
207: return;
208: truncsp(buf);
209: stripctrla(buf);
210: p=strrchr(buf,LF);
211: if(!p) p=buf;
212: else p++;
213: if(!strnicmp(p," � Synchronet � ",16))
214: p+=16;
215: if(!strnicmp(p," * Synchronet * ",16))
216: p+=16;
217: while(*p && *p<=SP) p++;
218: strcpy(tag,p);
219: FREE(buf);
220: }
221:
222:
223: #define FEED (1<<0)
224: #define LOCAL (1<<1)
225: #define APPEND (1<<2)
226: #define TAGS (1<<3)
227:
228: #define ROUTE (1<<1)
229: #define NODES (1<<2)
230: #define USERS (1<<3)
231:
232: char *usage="\nusage: qwknodes [/opts] cmds"
233: "\n"
234: "\n cmds: r = create ROUTE.DAT"
235: "\n u = create USERS.DAT"
236: "\n n = create NODES.DAT"
237: "\n"
238: "\n opts: f = format addresses for nodes that feed from this system"
239: "\n a = append existing output files"
240: "\n t = include tag lines in NODES.DAT"
241: "\n l = include local users in USERS.DAT"
242: "\n m# = maximum message age set to # days"
243: "\n";
244:
245: void main(int argc, char **argv)
246: {
247: char str[256],tmp[128],tag[256],addr[256],*p;
248: int i,j,mode=0,cmd=0,o_mode,max_age=0;
249: ushort smm,sbl;
250: ulong *crc=NULL,curcrc,total_crcs=0,l;
251: FILE *route,*users,*nodes;
252: time_t now;
253: read_cfg_text_t txt;
254: smbstatus_t status;
255: smbmsg_t msg;
256:
257: txt.openerr="\7\r\nError opening %s for read.\r\n";
258: txt.reading="\r\nReading %s...";
259: txt.readit="\rRead %s ";
260: txt.allocerr="\7\r\nError allocating %u bytes of memory\r\n";
261: txt.error="\7\r\nERROR: Offset %lu in %s\r\n\r\n";
262:
263: fprintf(stderr,"\nSynchronet QWKnet Node/Route/User List v1.20 "
264: "Developed 1995-1997 Rob Swindell\n");
265:
266:
267: for(i=1;i<argc;i++)
268: for(j=0;argv[i][j];j++)
269: switch(toupper(argv[i][j])) {
270: case '/':
271: case '-':
272: while(argv[i][++j])
273: switch(toupper(argv[i][j])) {
274: case 'F':
275: mode|=FEED;
276: break;
277: case 'L':
278: mode|=LOCAL;
279: break;
280: case 'A':
281: mode|=APPEND;
282: break;
283: case 'T':
284: mode|=TAGS;
285: break;
286: case 'M':
287: j++;
288: max_age=atoi(argv[i]+j);
289: while(isdigit(argv[i][j+1])) j++;
290: break;
291: default:
292: printf(usage);
293: exit(1); }
294: j--;
295: break;
296: case 'R':
297: cmd|=ROUTE;
298: break;
299: case 'U':
300: cmd|=USERS;
301: break;
302: case 'N':
303: cmd|=NODES;
304: break;
305: default:
306: printf(usage);
307: exit(1); }
308:
309: if(!cmd) {
310: printf(usage);
311: exit(1); }
312:
313: if(mode&APPEND)
314: o_mode=O_WRONLY|O_CREAT|O_APPEND;
315: else
316: o_mode=O_WRONLY|O_CREAT|O_TRUNC;
317:
318: if(cmd&NODES)
319: if((nodes=fnopen(&i,"NODES.DAT",o_mode))==NULL) {
320: printf("\7\nError opening NODES.DAT\n");
321: exit(1); }
322:
323: if(cmd&USERS)
324: if((users=fnopen(&i,"USERS.DAT",o_mode))==NULL) {
325: printf("\7\nError opening USERS.DAT\n");
326: exit(1); }
327:
328: if(cmd&ROUTE)
329: if((route=fnopen(&i,"ROUTE.DAT",o_mode))==NULL) {
330: printf("\7\nError opening ROUTE.DAT\n");
331: exit(1); }
332:
333: if(!node_dir[0]) {
334: p=getenv("SBBSNODE");
335: if(p==NULL) {
336: printf("\7\nSBBSNODE environment variable not set.\n");
337: exit(1); }
338: strcpy(node_dir,p); }
339:
340: strupr(node_dir);
341:
342: if(node_dir[strlen(node_dir)-1]!='\\')
343: strcat(node_dir,"\\");
344:
345: read_node_cfg(txt);
346: if(ctrl_dir[0]=='.') { /* Relative path */
347: strcpy(str,ctrl_dir);
348: sprintf(ctrl_dir,"%s%s",node_dir,str);
349: if(_fullpath(str,ctrl_dir,40))
350: strcpy(ctrl_dir,str); }
351: backslash(ctrl_dir);
352:
353: read_main_cfg(txt);
354: if(data_dir[0]=='.') { /* Relative path */
355: strcpy(str,data_dir);
356: sprintf(data_dir,"%s%s",node_dir,str);
357: if(_fullpath(str,data_dir,40))
358: strcpy(data_dir,str); }
359: backslash(data_dir);
360: read_msgs_cfg(txt);
361:
362: now=time(NULL);
363: smm=crc16("smm");
364: sbl=crc16("sbl");
365: fprintf(stderr,"\n\n");
366: for(i=0;i<total_subs;i++) {
367: if(!(sub[i]->misc&SUB_QNET))
368: continue;
369: fprintf(stderr,"%-*s %s\n"
370: ,LEN_GSNAME,grp[sub[i]->grp]->sname,sub[i]->lname);
371: sprintf(smb.file,"%s%s",sub[i]->data_dir,sub[i]->code);
372: smb.retry_time=30;
373: if((j=smb_open(&smb))!=0) {
374: printf("smb_open returned %d\n",j);
375: continue; }
376: if((j=smb_locksmbhdr(&smb))!=0) {
377: printf("smb_locksmbhdr returned %d\n",j);
378: smb_close(&smb);
379: continue; }
380: if((j=smb_getstatus(&smb))!=0) {
381: printf("smb_getstatus returned %d\n",j);
382: smb_close(&smb);
383: continue; }
384: smb_unlocksmbhdr(&smb);
385: msg.offset=status.total_msgs;
386: if(!msg.offset) {
387: smb_close(&smb);
388: printf("Empty.\n");
389: continue; }
390: while(!kbhit() && !ferror(smb.sid_fp) && msg.offset) {
391: msg.offset--;
392: fseek(smb.sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
393: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
394: break;
395: fprintf(stderr,"%-5lu\r",msg.offset+1);
396: if(msg.idx.to==smm || msg.idx.to==sbl)
397: continue;
398: if(max_age && now-msg.idx.time>((ulong)max_age*24UL*60UL*60UL))
399: continue;
400: if((j=smb_lockmsghdr(&smb,&msg))!=0) {
401: printf("smb_lockmsghdr returned %d\n",j);
402: break; }
403: if((j=smb_getmsghdr(&smb,&msg))!=0) {
404: printf("smb_getmsghdr returned %d\n",j);
405: break; }
406: smb_unlockmsghdr(&smb,&msg);
407: if((mode&LOCAL && msg.from_net.type==NET_NONE)
408: || msg.from_net.type==NET_QWK) {
409: if(msg.from_net.type!=NET_QWK)
410: msg.from_net.addr="";
411: if(cmd&USERS) {
412: sprintf(str,"%s%s",msg.from_net.addr,msg.from);
413: curcrc=crc32(str); }
414: else
415: curcrc=crc32(msg.from_net.addr);
416: for(l=0;l<total_crcs;l++)
417: if(curcrc==crc[l])
418: break;
419: if(l==total_crcs) {
420: total_crcs++;
421: if((crc=(ulong *)REALLOC(crc
422: ,sizeof(ulong)*total_crcs))==NULL) {
423: printf("Error allocating %lu bytes\n"
424: ,sizeof(ulong)*total_crcs);
425: break; }
426: crc[l]=curcrc;
427: if(cmd&ROUTE && msg.from_net.type==NET_QWK) {
428: strcpy(addr,msg.from_net.addr);
429: if(mode&FEED) {
430: p=strrchr(addr,'/');
431: if(!p)
432: p=addr;
433: else
434: *(p++)=0;
435: sprintf(str,"%s %s:%s%c%s"
436: ,unixtodstr(msg.hdr.when_written.time,tmp)
437: ,p,sys_id,p==addr ? 0 : '/'
438: ,addr);
439: fprintf(route,"%s\r\n",str); }
440: else {
441: p=strrchr(addr,'/');
442: if(p) {
443: *(p++)=0;
444: fprintf(route,"%s %s:%.*s\r\n"
445: ,unixtodstr(msg.hdr.when_written.time,str)
446: ,p
447: ,(uint)(p-addr)
448: ,addr); } } }
449: if(cmd&USERS) {
450: if(msg.from_net.type!=NET_QWK)
451: strcpy(str,sys_id);
452: else if(mode&FEED)
453: sprintf(str,"%s/%s",sys_id,msg.from_net.addr);
454: else
455: strcpy(str,msg.from_net.addr);
456: p=strrchr(str,'/');
457: if(p)
458: fprintf(users,"%-25.25s %-8.8s %s (%s)\r\n"
459: ,msg.from,p+1
460: ,unixtodstr(msg.hdr.when_written.time,tmp)
461: ,str);
462: else
463: fprintf(users,"%-25.25s %-8.8s %s\r\n"
464: ,msg.from,str
465: ,unixtodstr(msg.hdr.when_written.time,tmp)); }
466: if(cmd&NODES && msg.from_net.type==NET_QWK) {
467: if(mode&TAGS)
468: gettag(msg,tag);
469: if(mode&FEED)
470: sprintf(str,"%s/%s",sys_id,msg.from_net.addr);
471: else
472: strcpy(str,msg.from_net.addr);
473: p=strrchr(str,'/');
474: if(p) {
475: if(mode&TAGS)
476: fprintf(nodes,"%-8.8s %s\r\n"
477: ,p+1
478: ,tag);
479: else
480: fprintf(nodes,"%-8.8s %s (%s)\r\n"
481: ,p+1
482: ,unixtodstr(msg.hdr.when_written.time,tmp)
483: ,str); }
484: else
485: fprintf(nodes,"%-8.8s %s\r\n"
486: ,str
487: ,mode&TAGS
488: ? tag
489: : unixtodstr(msg.hdr.when_written.time,tmp)); }
490: } }
491: smb_freemsgmem(&msg); }
492:
493: smb_close(&smb);
494: if(kbhit()) {
495: getch();
496: fprintf(stderr,"Key pressed.\n");
497: break; } }
498: fprintf(stderr,"Done.\n");
499: }
500:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.