/********************************************************** * File: nodelist.c * Created at Thu Jul 15 16:14:36 1999 by pk // aaz@ruxy.org.ru * * $Id: nodelist.c,v 1.20 2003/02/04 17:30:46 cyrilm Exp $ **********************************************************/ #include "headers.h" char *NL_IDX="/qnode.idx"; char *NL_SIGN="qico nodelist index"; static int compare_ftnaddr(const void *a, const void *b) { const ftnaddr_t *aa = (const ftnaddr_t *)a; const ftnaddr_t *bb = (const ftnaddr_t *)b; int res; if((res = aa->z - bb->z)) return res; if((res = aa->n - bb->n)) return res; if((res = aa->f - bb->f)) return res; if((res = aa->p - bb->p)) return res; return 0; } int query_nodelist(ftnaddr_t *addr, char *nlpath, ninfo_t **nl) { ninfo_t *nlent=xmalloc(sizeof(ninfo_t)); FILE *idx; idxh_t ih; idxent_t ie; char nlp[MAX_PATH], str[MAX_STRING], *p, *t; int rc; struct stat sb; int l, r; *nl=NULL; memset(nlent, 0, sizeof(ninfo_t)); snprintf(nlp, MAX_PATH, "%s/%s.lock", nlpath, NL_IDX); if(islocked(nlp)) return 0; snprintf(nlp, MAX_PATH, "%s/%s", nlpath, NL_IDX); idx=fopen(nlp, "rb"); if(!idx) { xfree(nlent);return 1; } if(fread(&ih, sizeof(idxh_t), 1, idx)!=1) { fclose(idx); xfree(nlent);return 1; } if(strcmp(ih.sign, NL_SIGN)) { fclose(idx); xfree(nlent);return 1; } if(fstat(fileno(idx),&sb)) { fclose(idx); xfree(nlent);return 1; } l = 0; r = (sb.st_size-sizeof(idxh_t))/sizeof(idxent_t); rc = -1; while(l < r) { int m; m = (l+r)/2; if(fseek(idx, sizeof(idxh_t)+m*sizeof(idxent_t), SEEK_SET)) { fclose(idx); xfree(nlent);return 1; } if(fread(&ie, sizeof(ie), 1, idx) != 1) { fclose(idx); xfree(nlent);return 1; } rc = compare_ftnaddr(addr, &ie.addr); if(rc < 0) r = m; else if(rc > 0) l = m+1; else break; } fclose(idx); if(rc != 0) { xfree(nlent);return 0; } xstrcpy(nlp, nlpath, MAX_PATH);xstrcat(nlp, "/", MAX_PATH); xstrcat(nlp, ih.nlname[ie.index], MAX_PATH); if(stat(nlp,&sb)) { xfree(nlent);return 2; } else if(sb.st_mtime!=ih.nltime[ie.index]) { xfree(nlent);return 3; } idx=fopen(nlp, "rt"); if(!idx) { xfree(nlent);return 2; } fseek(idx, ie.offset, SEEK_SET); if(!fgets(str, MAX_STRING, idx)) { xfree(nlent);return 2; } fclose(idx);t=str; p=strsep(&t, ","); if(p) { if(!strcasecmp(p,"pvt")) nlent->type=NT_PVT; if(!strcasecmp(p,"hold")) nlent->type=NT_HOLD; if(!strcasecmp(p,"down")) nlent->type=NT_DOWN; if(!strcasecmp(p,"hub")) nlent->type=NT_HUB; } strsep(&t, ","); p=strsep(&t, ",");if(p) { strtr(p,'_',' ');nlent->name=xstrdup(p); p=strsep(&t, ","); if(p) { strtr(p,'_',' ');nlent->place=xstrdup(p); p=strsep(&t, ","); if(p) { strtr(p,'_',' ');nlent->sysop=xstrdup(p); p=strsep(&t, ","); if(p) { nlent->phone=xstrdup(p); p=strsep(&t, ","); if(p) { nlent->speed=atoi(p); p=strsep(&t, "\r\n\0"); if(p) nlent->flags=xstrdup(p); } } } } } nlent->haswtime=0; *nl=nlent; falist_add(&nlent->addrs, addr); return 0; } int is_listed_one(ftnaddr_t *addr, char *nlpath) { FILE *idx; idxh_t ih; idxent_t ie; int rc; char nlp[MAX_PATH]; struct stat sb; int l, r; xstrcpy(nlp, nlpath, MAX_PATH); xstrcat(nlp, NL_IDX, MAX_PATH); idx=fopen(nlp, "rb"); if(!idx) { return 0; } if(fread(&ih, sizeof(idxh_t), 1, idx)!=1) { return 0; } if(strcmp(ih.sign, NL_SIGN)) return 0; if(fstat(fileno(idx),&sb)) { fclose(idx); return 0; } l = 0; r = (sb.st_size-sizeof(idxh_t))/sizeof(idxent_t); rc = -1; while(l < r) { int m; m = (l+r)/2; if(fseek(idx, sizeof(idxh_t)+m*sizeof(idxent_t), SEEK_SET)) { fclose(idx); return 0; } if(fread(&ie, sizeof(ie), 1, idx) != 1) { fclose(idx); return 0; } rc = compare_ftnaddr(addr, &ie.addr); if(rc < 0) r = m; else if(rc > 0) l = m+1; else break; } fclose(idx); return rc == 0; } int is_listed(falist_t *addrs, char *nlpath, int needall) { falist_t *i; for(i=addrs;i;i=i->next) { if(needall) { if(!is_listed_one(&i->addr,nlpath)) return 0; } else { if(is_listed_one(&i->addr,nlpath)) return 1; } } return needall; } void phonetrans(char **pph, slist_t *phtr) { int rc=1;slist_t *pht; char *s, *t,*p, tmp[MAX_STRING]; char *ph = *pph; int len=0; if(!*pph || !*ph) return; for(pht=phtr;pht && rc;pht=pht->next) { s=xstrdup(pht->str); p=strchr(s,' '); if(p) { *(p++)='\0'; while(*p==' ') p++; t=strchr(p,' '); if(t) *t='\0'; } if(strncmp(ph, s, strlen(s))==0) { if(p) xstrcpy(tmp, p, MAX_STRING);else *tmp=0; xstrcat(tmp, ph+strlen(s), MAX_STRING); len=strlen(tmp)+1; xfree(ph); ph=xmalloc(len); *pph=ph; xstrcpy(ph, tmp, len);xfree(s); return; } if(s[0]=='=') { if(p) xstrcpy(tmp, p, MAX_STRING);else *tmp=0; xstrcat(tmp, ph, MAX_STRING); len=strlen(tmp)+1; xfree(ph); ph=xmalloc(len); *pph=ph; xstrcpy(ph, tmp, len);xfree(s); return; } xfree(s); } } /* most part of checktimegaps() was taken from ifcico-tx.sc by Alexey Gretchaninov */ int checktimegaps(char *ranges) { int firstDay, secondDay, firstHour, firstMinute, secondHour, secondMinute, firstMark, secondMark, currentMark, Day, Hour, Min; char *p, *s, *f, *rs, *r; time_t tim=time(NULL); struct tm *ti; if(!ranges) return 0; if(!strlen(ranges)) return 0; if(!(rs=xstrdup(ranges))) return 0; for(r=strtok(rs, ",");r;r=strtok(NULL, ",")) { while(*r==' ') r++; if(!*r) continue; if(!strcasecmp(r, "cm")) { xfree(rs); return 1;} if(!strcasecmp(r, "never")) { xfree(rs); return 0;} if(r[0]=='T') { if(chktxy(r)) { xfree(rs); return 1;} else continue; } firstDay = -1; secondDay = -1; firstHour = -1; firstMinute = -1; secondHour = -1; secondMinute = -1; if((p = strchr(r, '-'))) { if((s = strchr(r, '.'))) { firstDay = atoi(s - 1); firstHour = atoi(s + 1); if((f = strchr(s + 1, ':')) && f < p) firstMinute = atoi(f + 1); if((s = strchr(p + 1, '.'))) { secondDay = atoi(s - 1); secondHour = atoi(s + 1); if((f = strchr(s + 1, ':'))) secondMinute = atoi(f + 1); } else { xfree(rs); return 0; } } else { firstHour = atoi(r); if((f = strchr(r, ':')) && f < p) firstMinute = atoi(f + 1); secondHour = atoi(p + 1); if((f = strchr(p + 1, ':'))) secondMinute = atoi(f + 1); } } else { if((s = strchr(r, '.'))) { firstDay = atoi(s - 1); firstHour = atoi(s + 1); if((p = strchr(s + 1,':'))) firstMinute = atoi(p + 1); } else { firstHour = atoi(r); if((p = strchr(r,':'))) firstMinute = atoi(p + 1); } } if( firstDay < -1 || firstDay > 7 || firstDay == 0 || firstHour < -1 || firstHour > 23 || firstMinute< -1 || firstMinute > 59 || secondDay < -1 || secondDay > 7 || secondDay == 0 || secondHour < -1 || secondHour > 24 || secondMinute < -1 || secondMinute > 59 || firstHour == -1 || (secondDay != -1 && secondHour==-1)) { xfree(rs);return 0; } ti=localtime(&tim); Day=ti->tm_wday;if(!Day) Day = 7; Hour=ti->tm_hour;Min=ti->tm_min; firstMark = firstHour * 60; if(firstMinute != -1) firstMark += firstMinute; secondMark = secondHour * 60; if(secondMinute != -1) secondMark += secondMinute; currentMark = Hour * 60 + Min; /* write_log("%d.%d:%d-%d.%d:%d %d.%d:%d", */ /* firstDay,firstHour,firstMinute, */ /* secondDay,secondHour,secondMinute, */ /* Day,Hour,Min); */ if(secondDay != -1) { if(firstDay < secondDay) { if(Day >= firstDay && Day <= secondDay) { if(firstMark < secondMark) { if(currentMark >= firstMark && currentMark < secondMark) { xfree(rs); return 1; } } else { if(currentMark >= firstMark || currentMark < secondMark) { xfree(rs); return 1; } } } } else { if(firstDay == secondDay) { if(Day == firstDay) { if(firstMark <= secondMark) { if(currentMark >= firstMark && currentMark < secondMark) { xfree(rs); return 1;} } else { if(currentMark >= firstMark || currentMark < secondMark) { xfree(rs); return 1;} } } } else { if(Day >= firstDay || Day <= secondDay) { if(firstMark <= secondMark) { if(currentMark >= firstMark && currentMark < secondMark) { xfree(rs); return 1;} } else { if(currentMark >= firstMark || currentMark < secondMark) { xfree(rs); return 1;} } } } } } else if(secondHour != -1) { if(firstMark <= secondMark) { if(currentMark >= firstMark && currentMark < secondMark) { xfree(rs); return 1;} } else { if(currentMark >= firstMark || currentMark < secondMark) { xfree(rs); return 1;} } } else if(firstDay != -1) { if(firstMinute != -1) { if(Day == firstDay && Hour == firstHour && Min == firstMinute) { xfree(rs); return 1;} } else { if(Day == firstDay && Hour == firstHour) { xfree(rs); return 1;} } } else { if(firstMinute != -1) { if(Hour == firstHour && Min == firstMinute) { xfree(rs); return 1;} } else { if(Hour == firstHour) { xfree(rs); return 1;} } } } xfree(rs); return 0; } int chktxy(char *p) { time_t tim=time(NULL); struct tm *ti=gmtime(&tim); int t=ti->tm_hour*60+ti->tm_min, t1, t2; t1=(toupper((int)p[1])-'A')*60+(islower((int)p[1]) ? 30:0); t2=(toupper((int)p[2])-'A')*60+(islower((int)p[2]) ? 30:0); return ((t1<=t2 && t>=t1 && t<=t2) || (t1>t2 && (t>=t1 || t<=t2))); } int checktxy(char *flags) { char *u, *p, *w; int i; w=xstrdup(flags);u=w; while((p=strsep(&u, ","))) { if(!strcmp(p,"CM")) { xfree(w); return 1; } if(p[0]=='T' && p[3]==0) { i=chktxy(p); xfree(w); return i; } } xfree(w); return 0; } subst_t *findsubst(ftnaddr_t *fa, subst_t *subs) { while(subs && !ADDRCMP((*fa), subs->addr)) subs=subs->next; return subs; } subst_t *parsesubsts(faslist_t *sbs) { subst_t *subs=NULL,*q;char *p,*t; dialine_t *d, *c; while(sbs) { q=findsubst(&sbs->addr, subs); if(!q) { q=xmalloc(sizeof(subst_t)); q->next=subs;subs=q; ADDRCPY(q->addr, sbs->addr); q->hiddens=q->current=NULL; q->nhids=0; } d=xmalloc(sizeof(dialine_t)); /* Insert ind _end_ of list */ c=q->hiddens; if(!c) { q->current=q->hiddens=d; } else { while(c->next)c=c->next; c->next=d; } d->next=NULL; d->num=++q->nhids; d->phone=NULL; d->timegaps=NULL; p=sbs->str; while(*p==' ') p++; t=strsep(&p, " "); if(t) { if(*t!='-') d->phone=xstrdup(t); if(p) { while(*p==' ') p++; t=strsep(&p, " "); if(t) if(*t!='-') d->timegaps=xstrdup(t); } } sbs=sbs->next; } return subs; } int applysubst(ninfo_t *nl, subst_t *subs) { subst_t *sb=findsubst(&nl->addrs->addr, subs); dialine_t *d; ninfo_t *from_nl = NULL; if(!sb) return 0; d=sb->current; sb->current=sb->current->next; if(!sb->current) sb->current=sb->hiddens; if(!d->phone) query_nodelist(&nl->addrs->addr,cfgs(CFG_NLPATH),&from_nl); if(d->phone) { if(nl->phone) xfree(nl->phone); nl->phone=xstrdup(d->phone); } else if(from_nl && from_nl->phone) { if(nl->phone) xfree(nl->phone); nl->phone=xstrdup(from_nl->phone); if(cfgi(CFG_TRANSLATESUBST) == 0) phonetrans(&rnode->phone, cfgsl(CFG_PHONETR)); } if(d->timegaps) { if(nl->wtime) xfree(nl->wtime); nl->wtime=xstrdup(d->timegaps); nl->haswtime=1; } else { if(nl->wtime) xfree(nl->wtime); nl->haswtime=0; } nl->hidnum=(sb->nhids>1)?d->num:0; if(from_nl) nlkill(&from_nl); return 1; } void killsubsts(subst_t **l) { subst_t *t; dialine_t *d, *e; while(l && *l) { t=(*l)->next; d=(*l)->hiddens; while(d) { e=d->next; xfree(d->phone);xfree(d->timegaps); xfree(d); d=e; } xfree(*l); *l=t; } } int can_dial(ninfo_t *nl, int ct) { char *p;int d=0; if(!nl) return 0; if(!*nl->phone) return 0; for(p=nl->phone;*p;p++) if(!strchr("0123456789*#TtPpRr,.\"Ww@!-",*p)) d++; if(d>0) return 0; if(ct) return 1; if(nl->haswtime) return checktimegaps(nl->wtime); if(nl->type==NT_HOLD||nl->type==NT_DOWN||nl->type==NT_PVT) return 0; if(checktxy(nl->flags)) return 1; if(nl->addrs->addr.p==0 && checktimegaps(cfgs(CFG_ZMH))) return 1; return 0; } int find_dialable_subst(ninfo_t *nl, int ct, subst_t *subs) { int start; applysubst(nl,subs); start = nl->hidnum; while (!can_dial(nl,ct) && nl->hidnum && applysubst(nl,subs) && nl->hidnum != start); return can_dial(nl,ct); } void nlfree(ninfo_t *nl) { if(!nl) return; falist_kill(&(nl)->addrs); xfree(nl->name); xfree(nl->place); xfree(nl->sysop); xfree(nl->phone); xfree(nl->wtime); xfree(nl->flags); xfree(nl->pwd); xfree(nl->mailer); } void nlkill(ninfo_t **nl) { if(!*nl) return; nlfree(*nl); xfree(*nl); }