|
|
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.