Skip to content
Snippets Groups Projects
qwknodes.c 9.86 KiB
Newer Older
/* Synchronet QWKnet node list or route.dat file generator */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "load_cfg.h"
#include "str_util.h"
#include "date_str.h"
#include "smblib.h"
#include "nopen.h"
#include "crc16.h"
#include "crc32.h"
#include "conwrap.h"	/* kbhit */
#include <stdarg.h>

unsigned _stklen=10000;
smb_t		smb;
scfg_t		cfg;

void stripctrla(char *str)
	for(i=j=0;str[i] && j<sizeof(out)-1;i++) {
		if(str[i]==CTRL_A && str[i+1]!=0)
			i++;
		else
			out[j++]=str[i]; 
	}
	out[j]=0;
	strcpy(str,out);
int lputs(char* str)
{
    char tmp[256];
    int i,j,k;

	j=strlen(str);
	for(i=k=0;i<j;i++)      /* remove CRs */
		if(str[i]==CR && str[i+1]==LF)
			continue;
		else
			tmp[k++]=str[i];
	tmp[k]=0;
	return(fputs(tmp,stdout));
}
/****************************************************************************/
/* Performs printf() through local assembly routines                        */
/* Called from everywhere                                                   */
/****************************************************************************/
int lprintf(const char *fmat, ...)
{
	va_list argptr;
	char sbuf[256];
	int chcount;

	va_start(argptr,fmat);
	chcount=vsnprintf(sbuf,sizeof(sbuf),fmat,argptr);
	va_end(argptr);
	lputs(sbuf);
	return(chcount);
}
void bail(int code)
{
char *loadmsgtail(smbmsg_t* msg)
{
	char	*buf=NULL;
deuce's avatar
deuce committed
	uint16_t	xlat;
	int 	i;
	long	l=0,length;

	for(i=0;i<msg->hdr.total_dfields;i++) {
		if(msg->dfield[i].type!=TEXT_TAIL)
			continue;
		fseek(smb.sdt_fp,msg->hdr.offset+msg->dfield[i].offset
			,SEEK_SET);
		if(fread(&xlat,2,1,smb.sdt_fp) != 1)
			xlat = XLAT_NONE;
		if(xlat!=XLAT_NONE) 		/* no translations supported */
			continue;
		length=msg->dfield[i].length-2;
		if((buf=realloc_or_free(buf,l+msg->dfield[i].length+1))==NULL)
			return(buf);
		l+=fread(buf+l,1,length,smb.sdt_fp);
		buf[l]=0; 
	}
	return(buf);
void gettag(smbmsg_t* msg, char *tag)
	tag[0]=0;
	buf=loadmsgtail(msg);
	if(buf==NULL)
		return;
	truncsp(buf);
	stripctrla(buf);
	p=strrchr(buf,LF);
	if(!p) p=buf;
	else p++;
	if(!strnicmp(p,"  Synchronet  ",16))
		p+=16;
	if(!strnicmp(p," * Synchronet * ",16))
		p+=16;
	while(*p && *p<=' ') p++;
	strcpy(tag,p);
	free(buf);
}


#define FEED   (1<<0)
#define LOCAL  (1<<1)
#define APPEND (1<<2)
#define TAGS   (1<<3)

#define ROUTE  (1<<1)
#define NODES  (1<<2)
#define USERS  (1<<3)

char *usage="\nusage: qwknodes [-opts] cmds"
			"\n cmds: r  =  create route.dat"
			"\n       u  =  create users.dat"
			"\n       n  =  create nodes.dat"
			"\n"
			"\n opts: f  =  format addresses for nodes that feed from this system"
			"\n       a  =  append existing output files"
			"\n       t  =  include tag lines in nodes.dat"
			"\n       l  =  include local users in users.dat"
deuce's avatar
deuce committed
			"\n       m# =  maximum message age set to # days";
int main(int argc, char **argv)
	char		str[256],tmp[128],tag[256],addr[256],*p;
	int 		i,j,mode=0,cmd=0,o_mode,max_age=0;
	ushort		smm,sbl;
	uint32_t	*crc=NULL,curcrc,total_crcs=0,l;
	FILE		*route=NULL,*users=NULL,*nodes=NULL;
	time_t		now;
	smbmsg_t	msg;
	const char*	revision = "1.26";
	fprintf(stdout,"\nSynchronet QWKnet Node/Route/User List Generator v%s-%s\n"
		,revision, PLATFORM_DESC);

	for(i=1;i<argc;i++)
		for(j=0;argv[i][j];j++)
			switch(toupper(argv[i][j])) {
				case '/':
				case '-':
					while(argv[i][++j])
						switch(toupper(argv[i][j])) {
							case 'F':
								mode|=FEED;
								break;
							case 'L':
								mode|=LOCAL;
								break;
							case 'A':
								mode|=APPEND;
								break;
							case 'T':
								mode|=TAGS;
								break;
							case 'M':
								j++;
								max_age=atoi(argv[i]+j);
								while(isdigit(argv[i][j+1])) j++;
								break;
							default:
deuce's avatar
deuce committed
								puts(usage);
				case 'R':
					cmd|=ROUTE;
					break;
				case 'U':
					cmd|=USERS;
					break;
				case 'N':
					cmd|=NODES;
					break;
				default:
deuce's avatar
deuce committed
					puts(usage);
					return(1); 
		}

	if(!cmd) {
deuce's avatar
deuce committed
		puts(usage);
		return(1); 
	}

	if(mode&APPEND)
		o_mode=O_WRONLY|O_CREAT|O_APPEND;
	else
		o_mode=O_WRONLY|O_CREAT|O_TRUNC;

	if(cmd&NODES)
		if((nodes=fnopen(&i,"nodes.dat",o_mode))==NULL) {
			printf("\7\nError opening nodes.dat\n");
			return(1); 
		}

	if(cmd&USERS)
		if((users=fnopen(&i,"users.dat",o_mode))==NULL) {
			printf("\7\nError opening users.dat\n");
			return(1); 
		}

	if(cmd&ROUTE)
		if((route=fnopen(&i,"route.dat",o_mode))==NULL) {
			printf("\7\nError opening route.dat\n");
			return(1); 
		}

	cfg.size=sizeof(cfg);
	SAFECOPY(cfg.ctrl_dir, get_ctrl_dir(/* warn: */TRUE));
	if(!load_cfg(&cfg, /* text: */NULL, /* prep: */TRUE, /* node: */FALSE, str, sizeof(str))) {
		printf("\7\n%s\n",str);
	}

	now=time(NULL);
	smm=crc16("smm",0);
	sbl=crc16("sbl",0);
	for(i=0;i<cfg.total_subs;i++) {
		if(!(cfg.sub[i]->misc&SUB_QNET))
			continue;
		fprintf(stdout,"%-*s  %s\n"
			,LEN_GSNAME,cfg.grp[cfg.sub[i]->grp]->sname,cfg.sub[i]->lname);
		SAFEPRINTF2(smb.file,"%s%s",cfg.sub[i]->data_dir,cfg.sub[i]->code);
		smb.retry_time=30;
		smb.subnum=i;
		if((j=smb_open(&smb))!=0) {
			fprintf(stderr, "smb_open returned %d\n",j);
			continue; 
		}
		if((j=smb_locksmbhdr(&smb))!=0) {
			fprintf(stderr, "smb_locksmbhdr returned %d\n",j);
			smb_close(&smb);
			continue; 
		}
		if((j=smb_getstatus(&smb))!=0) {
			fprintf(stderr, "smb_getstatus returned %d\n",j);
			smb_close(&smb);
			continue; 
		}
		smb_unlocksmbhdr(&smb);
		msg.idx_offset=smb.status.total_msgs;
		if(!msg.idx_offset) {
			smb_close(&smb);
			printf("Empty.\n");
			continue; 
		}
		while(!kbhit() && !ferror(smb.sid_fp) && msg.idx_offset) {
			msg.idx_offset--;
			fseek(smb.sid_fp,msg.idx_offset*sizeof(idxrec_t),SEEK_SET);
			if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
				break;
			fprintf(stdout,"%-5u\r",msg.idx_offset+1);
			if(msg.idx.to==smm || msg.idx.to==sbl)
				continue;
			if(max_age && now-msg.idx.time>((time_t)max_age*24UL*60UL*60UL))
				continue;
			if((j=smb_lockmsghdr(&smb,&msg))!=0) {
				fprintf(stderr, "smb_lockmsghdr returned %d\n",j);
				break; 
			}
			if((j=smb_getmsghdr(&smb,&msg))!=0) {
				fprintf(stderr, "smb_getmsghdr returned %d\n",j);
				break; 
			}
			smb_unlockmsghdr(&smb,&msg);
			if((mode&LOCAL && msg.from_net.type==NET_NONE)
				|| (msg.from_net.type==NET_QWK && msg.from_net.addr!=NULL)) {
				if(msg.from_net.type!=NET_QWK)
					msg.from_net.addr="";
				if(cmd&USERS) {
deuce's avatar
deuce committed
					sprintf(str,"%s%s",(char *)msg.from_net.addr,(char *)msg.from);
					curcrc=crc32(str,0); 
				}
				else
					curcrc=crc32(msg.from_net.addr,0);
				for(l=0;l<total_crcs;l++)
					if(curcrc==crc[l])
						break;
				if(l==total_crcs) {
					total_crcs++;
					if((crc=(uint32_t *)realloc_or_free(crc
						,sizeof(uint32_t)*total_crcs))==NULL) {
						printf("Error allocating %lu bytes\n"
							,sizeof(uint32_t)*total_crcs);
						break; 
					}
					crc[l]=curcrc;
					if(cmd&ROUTE && msg.from_net.type==NET_QWK) {
						strcpy(addr,msg.from_net.addr);
						if(mode&FEED) {
							p=strrchr(addr,'/');
							if(!p)
								p=addr;
							else
								*(p++)=0;
							safe_snprintf(str, sizeof(str), "%s %s:%s%c%s"
								,unixtodstr(&cfg,msg.hdr.when_written.time,tmp)
								,p,cfg.sys_id,p==addr ? 0 : '/'
								,addr);
							fprintf(route,"%s\r\n",str); 
						}
						else {
							p=strrchr(addr,'/');
							if(p) {
								*(p++)=0;
							fprintf(route,"%s %s:%.*s\r\n"
								,unixtodstr(&cfg,msg.hdr.when_written.time,str)
								,p
								,(uint)(p-addr)
								,addr); 
							} 
						} 
					}
					if(cmd&USERS) {
						if(msg.from_net.type!=NET_QWK)
							strcpy(str,cfg.sys_id);
						else if(mode&FEED)
deuce's avatar
deuce committed
							sprintf(str,"%s/%s",cfg.sys_id,(char *)msg.from_net.addr);
							strcpy(str,msg.from_net.addr);
						p=strrchr(str,'/');
						if(p)
							fprintf(users,"%-25.25s  %-8.8s  %s  (%s)\r\n"
								,msg.from,p+1
								,unixtodstr(&cfg,msg.hdr.when_written.time,tmp)
								,str);
						else
							fprintf(users,"%-25.25s  %-8.8s  %s\r\n"
								,msg.from,str
								,unixtodstr(&cfg,msg.hdr.when_written.time,tmp)); 
					}
					if(cmd&NODES && msg.from_net.type==NET_QWK) {
						if(mode&TAGS)
							gettag(&msg,tag);
						if(mode&FEED)
deuce's avatar
deuce committed
							sprintf(str,"%s/%s",cfg.sys_id,(char *)msg.from_net.addr);
						else
							strcpy(str,msg.from_net.addr);
						p=strrchr(str,'/');
						if(p) {
							if(mode&TAGS)
								fprintf(nodes,"%-8.8s  %s\r\n"
									,p+1
									,tag);
							else
								fprintf(nodes,"%-8.8s  %s  (%s)\r\n"
									,p+1
									,unixtodstr(&cfg,msg.hdr.when_written.time,tmp)
									,str); 
						}
						else
							fprintf(nodes,"%-8.8s  %s\r\n"
								,str
								,mode&TAGS
								? tag
								: unixtodstr(&cfg,msg.hdr.when_written.time,tmp)); 
					}
				} 
			}
			smb_freemsgmem(&msg); 
		}

		smb_close(&smb);
		if(kbhit()) {
			getch();
			fprintf(stdout,"Key pressed.\n");
	fprintf(stdout,"Done.\n");