/*
tossing functions
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <dirent.h>
#include "config.h"
list_t *newareas_descs;
list_t *newareas_users;
int crc32_ignore; /* initializated from gtic.c */
void swap_uid_gid()
{
setreuid(geteuid(),getuid());
setregid(getegid(),getgid());
}
int check_replaces(char *name,char *replaces)
/* Check "Replaces" keyword from tic. Return TRUE when ok.
Usually arguments is tic_t->file and tic_t->replaces.
*/
{
char *n,*r;
if(name==NULL || replaces==NULL) return FALSE;
/* if we found ? or * in name, return FALSE */
if(strchr(name,'?') || strchr(name,'*')) return FALSE;
/* simple compare with ignoring case */
if(strcasecmp(name,replaces) == 0) return TRUE;
/* Strip extension of name and replaces and compare it. If extention not
exist, return FALSE. If stripped name!=replaces, return FALSE.
TODO: most right method need...
*/
if(strchr(name,'.')==NULL || strchr(replaces,'.')==NULL) return FALSE;
n=xstrcpy(name);
r=xstrcpy(replaces);
/* strip extension */
strrchr(n,'.')[0]=0;
strrchr(r,'.')[0]=0;
if(strcasecmp(n,r)==0 && n[0]!=0 && r[0]!=0)
{
xfree(n);
xfree(r);
return TRUE;
}
xfree(n);
xfree(r);
return FALSE;
}
int validate_group(area_t *a,user_t *u)
/* Validate user_t groups for area_t. Returns TRUE when ok. */
{
int i; char *cur_group;
ass(a!=NULL);
ass(u!=NULL);
if(a->group==NULL) return TRUE; /* area group check disabled for this area */
for(i=0;i<list_head_max(u->groups);i++)
{
cur_group=list_get_key(u->groups,i);
if(cur_group[0]!='!') continue;
if(!strcasecmp(a->group,cur_group+1)) return FALSE;
if(wildmat_icase(a->group,cur_group+1)) return FALSE;
}
for(i=0;i<list_head_max(u->groups);i++)
{
cur_group=list_get_key(u->groups,i);
if(cur_group[0]=='!') continue;
if(!strcasecmp(a->group,cur_group)) return TRUE;
if(wildmat_icase(a->group,cur_group)) return TRUE;
}
return FALSE;
}
static void process_gtic_q_dir(char *dirname)
/*
* Process gtic_q directory. Add gtic_q\* to dirname\* when dirname\*.bsy not
* found (sorry for backslashes ;-).
* */
{
DIR *dir; struct dirent *dirp; struct stat st_buf;
char buff[PATH_MAX],ftmp[NAME_MAX],infile[PATH_MAX];
strcpy(buff,dirname); strcat(buff,"/gtic_q");
dir=opendir(buff);
if(dir==NULL) return;
while(1)
{
dirp=readdir(dir);
if(dirp==NULL) break;
strcpy(buff,dirname); strcat(buff,"/gtic_q/"); strcat(buff,dirp->d_name);
if(stat(buff,&st_buf)) continue;
if(!(st_buf.st_mode & S_IFREG)) continue;
strcpy(ftmp,dirp->d_name);
if(strchr(ftmp,'.')) strcpy(strrchr(ftmp,'.'),".bsy");
strcpy(buff,dirname); strcat(buff,"/"); strcat(buff,ftmp);
if(access_via_stat(buff,F_OK)==0) continue; /* bsy found - skip */
strcpy(buff,dirname);
strcat(buff,"/");
strcat(buff,dirp->d_name);
strcpy(infile,dirname);
strcat(infile,"/gtic_q/");
strcat(infile,dirp->d_name);
if(cp_add(infile,buff))
{
l_printf("unable to add %s to %s",infile,buff);
continue;
}
l_printf("OK_GTIC_Q: %s",infile);
remove(infile);
}
strcpy(buff,dirname); strcat(buff,"/gtic_q"); rmdir(buff);
closedir(dir);
}
void process_gtic_q()
/* scan gtic_q directories in outbound and try to fix bsy'ed xlo's */
{
char buff[PATH_MAX]; DIR *dir; struct dirent *dirp;
struct stat stat_buf;
int i;
char *cur_outbound;
for(i=0;i<ilist_head_max(domains);i++)
{
cur_outbound=ilist_get_entry(domains,i);
ass(cur_outbound!=NULL);
process_gtic_q_dir(cur_outbound);
dir=opendir(cur_outbound);
if(dir==NULL) continue;
while(1)
{
dirp=readdir(dir);
if(dirp==NULL) break;
if(wildmat_icase(dirp->d_name,"*.pnt")==0) continue;
snprintf(buff,sizeof(buff)-1,"%s/%s",cur_outbound,dirp->d_name);
if(stat(buff,&stat_buf)) continue;
if(!(stat_buf.st_mode & S_IFDIR)) continue;
process_gtic_q_dir(buff);
}
closedir(dir);
}
}
static int write_to_xlo(char *xlo,char *text,int kill,char *bsy,int mk_bsy)
{
FILE *fp,*fp_bsy=NULL;
char *p,prev=0;
if(mk_bsy==TRUE)
fp_bsy=fopen(bsy,"a");
fp=fopen(xlo,"a");
if(fp==NULL)
{
if(fp_bsy)
ass(fclose(fp_bsy)==0);
return 1;
}
p=text;
if(text[0]=='^') { kill=1; p++; }
if(kill==1) fputc('^',fp);
while(*p)
{
if(*p == '/' && prev=='/') { p++; continue; }
prev=*p;
fputc(prev,fp);
p++;
}
fputc('\n',fp);
/* fprintf(fp,"%s%s\n",kill?"^":"",text); */
ass(fclose(fp)==0);
if(mk_bsy==TRUE)
{
if(fp_bsy)
ass(fclose(fp_bsy)==0);
remove(bsy);
}
return 0;
}
static void mk_badname(ticlist_t *tlcur)
/* make tlcur->badname for renaming .tic to .bad */
{
char buff[PATH_MAX]; char *p;
strcpy(buff,tlcur->name);
p=strrchr(buff,'.');
if(p) p[0]=0;
strcat(buff,".bad");
tlcur->badname=xstrcpy(buff);
}
void create_outbound(void)
/* create outbound: copy files if hardlinks==1, make xlo's */
{
int i,j,k,mk_bsy,first_file; user_t *utmp; FILE *fp;
char xlo[PATH_MAX],qdir[PATH_MAX],bsy[PATH_MAX],out_path[PATH_MAX];
char previous_file[PATH_MAX],ftmp[PATH_MAX],xlo_str[PATH_MAX+1];
char buff[BUFSIZE],in_path[PATH_MAX];
int real_make_hardlinks; /* set to TRUE when area is "passthru" or
make_hardlinks==1 */
tic_t *newtic; ticlist_t *tlcur; area_t *acur; tic_t *tic;
char *p;
for(i=0;i<ticlist_list_max;i++)
{
tlcur=ilist_find_entry(ticlist_list,i);
ass(tlcur!=NULL);
if(tlcur->bad==TRUE) continue;
tic=tlcur->tic;
ass(tic!=NULL);
acur=list_find_entry(areas,tic->area);
ass(acur!=NULL);
/* printf("DEBUG: list_head_max = %d\n",list_head_max(acur->users)); */
first_file=TRUE;
real_make_hardlinks=make_hardlinks;
if(acur->flags & AREA_PASSTHRU) real_make_hardlinks=TRUE;
for(j=0;j<list_head_max(acur->users);j++)
{
utmp=list_get_entry(acur->users,j);
ass(utmp!=NULL);
/* printf("DEBUG: utmp=%p\n",utmp); */
if(utmp->flags & USER_PAUSE) continue;
if(nodecmp(&(utmp->addr),&(tic->from))==0) continue;
if(nodecmp(&(utmp->addr),&(tic->origin))==0) continue;
nodetoftn(ftmp,&(utmp->addr));
if(list_find(tic->seenby,ftmp)) continue;
/* check for area group */
if(!validate_group(acur,utmp))
{
l_printf("SKIP: area=%s, group=%s - node %s don't have this group.",
acur->name,acur->group,ftmp);
continue;
}
/*
printf("DEBUG: ok (%d:%d/%d.%d, node %s, tic %s)\n",
(utmp->addr).zone,
(utmp->addr).net,
(utmp->addr).node,
(utmp->addr).point,
ftmp,tlcur->name);
*/
/* make new tic */
newtic=copytic(tic);
/* from */
if(acur->aka)
nodecpy(&(newtic->from),acur->aka);
else
nodecpy(&(newtic->from),&whoami);
/* to */
nodecpy(&(newtic->to),&(utmp->addr));
/* password */
if(newtic->pw) xfree(newtic->pw);
newtic->pw=xstrcpy(utmp->passwd);
/* created by */
if(newtic->created) xfree(newtic->created);
newtic->created=xstrcpy(
"by gtic " VERSION " Copyright (C) 1998 Yuri Kuzmenko 2:463/169"
);
/* path, assumes newtic->path!=NULL */
ass(newtic->path!=NULL);
snprintf(buff,sizeof(buff)-1,"%s %lu %s",
acur->aka?nodetoftn(NULL,acur->aka):nodetoftn(NULL,&whoami),
(unsigned long)time(NULL),texttime(1));
p=xstrcpy(buff);
ilist_add(newtic->path,newtic->max_path++,p);
/* seenby, assumes newtic->seenby!=NULL */
ass(newtic->seenby!=NULL);
for(k=0;k<list_head_max(acur->users);k++)
{
user_t *utmp;
utmp=list_get_entry(acur->users,k);
ass(utmp!=NULL);
if((utmp->addr).point!=0 && add_point_seenby==0) continue;
nodetoftn(ftmp,&(utmp->addr));
if(list_find(newtic->seenby,ftmp)==NULL)
list_add(newtic->seenby,ftmp,"");
}
/* kill magic, from_pwd (by FSC-0087) */
if(newtic->magic) { xfree(newtic->magic); newtic->magic=NULL; }
if(newtic->from_pwd) { xfree(newtic->from_pwd); newtic->from_pwd=NULL; }
/* if areadesc absent in tic and area has description, add it */
if(newtic->areadesc==NULL && acur->desc!=NULL)
newtic->areadesc=xstrcpy(acur->desc);
/* make base of outbound file name */
#ifndef AMIGA4D
if(utmp->addr.point!=0)
snprintf(ftmp,sizeof(ftmp)-1,"%04x%04x.pnt/%08x",
utmp->addr.net,utmp->addr.node,utmp->addr.point);
else
snprintf(ftmp,sizeof(ftmp)-1,"%04x%04x",utmp->addr.net,utmp->addr.node);
#else
snprintf(ftmp,sizeof(ftmp)-1,"%d.%d.%d.%d", utmp->addr.zone,
utmp->addr.net, utmp->addr.node, utmp->addr.point);
#endif /* AMIGA4D */
/* determine queue directory */
strcpy(qdir,get_outbound(utmp->addr.zone)); strcat(qdir,"/");
strcat(qdir,ftmp); strcat(qdir,".gtq/");
mkdirs(qdir,dirmode(outbound_mode));
/* printf("DEBUG: qdir=%s, utmp=%p\n",qdir,utmp); */
/* determine bsy file and mk_bsy (make bsy?) variable */
strcpy(bsy,get_outbound(utmp->addr.zone)); strcat(bsy,"/");
strcat(bsy,ftmp); strcat(bsy,".bsy");
if(access_via_stat(bsy,F_OK)==0) /* bsy exist */
mk_bsy=FALSE;
else
mk_bsy=TRUE;
/* determine flo or hlo file name (if mk_bsy is FALSE, add gtic_q dir) */
/*
outbound[/gtic_q]/xxxxyyyy.xlo
outbound/xxxxyyyy.pnt[/gtic_q]/zzzzzzzz.xlo
*/
strcpy(xlo,get_outbound(utmp->addr.zone)); strcat(xlo,"/");
#ifndef AMIGA4D
if(utmp->addr.point!=0)
{
snprintf(ftmp,sizeof(ftmp)-1,"%04x%04x.pnt/",
utmp->addr.net,utmp->addr.node);
strcat(xlo,ftmp);
}
#endif /* AMIGA4D */
if(mk_bsy==FALSE)
{
strcat(xlo,"gtic_q/");
mkdirs(xlo,dirmode(outbound_mode));
}
#ifndef AMIGA4D
if(newtic->to.point!=0)
snprintf(ftmp,sizeof(ftmp)-1,"%08x",newtic->to.point);
else
snprintf(ftmp,sizeof(ftmp)-1,"%04x%04x",newtic->to.net,newtic->to.node);
#else
snprintf(ftmp,sizeof(ftmp)-1,"%d.%d.%d.%d", newtic->to.zone,
newtic->to.net, newtic->to.node, newtic->to.point);
#endif /* AMIGA4D */
if(utmp->flags & USER_HOLD)
strcat(ftmp,".hlo");
else
strcat(ftmp,".flo");
strcat(xlo,ftmp);
/* write new tic file */
/* first find correct tic name */
/* if user has no_tics flag, skip file */
if( ! (utmp->flags & USER_NO_TICS) )
{
while(1)
{
snprintf(ftmp,sizeof(ftmp)-1,"%s/%08lx.tic",qdir,
(long)time(NULL)+rand());
if(access_via_stat(ftmp,F_OK)) break;
}
fp=fopen(ftmp,"wb");
if(fp==NULL)
{
freetic(newtic);
tlcur->bad=TRUE;
mk_badname(tlcur);
l_printf("BADTIC: tic=%s, area %s, file %s, unable to open newtic %s",
tlcur->name,newtic->area,newtic->file,ftmp);
break;
}
if(writeticFILE(newtic,fp))
{
freetic(newtic);
tlcur->bad=TRUE;
mk_badname(tlcur);
l_printf("BADTIC: tic=%s, area %s, file %s, unable to write newtic %s"
,tlcur->name,newtic->area,newtic->file,ftmp);
break;
}
ass(fclose(fp)==0);
}
/*
try to make hardlinks or copy of file if hardlinks==TRUE
*/
snprintf(xlo_str,sizeof(xlo_str)-1,"%s/%s",acur->path,newtic->file);
if(real_make_hardlinks==TRUE)
{
/* get file from inbound if current area is "passthru" */
if(acur->flags & AREA_PASSTHRU)
snprintf(in_path,sizeof(in_path)-1,"%s/%s",inbound,newtic->realname);
else
snprintf(in_path,sizeof(in_path)-1,"%s/%s",acur->path,newtic->file);
if(first_file==TRUE)
{
strcpy(previous_file,in_path);
first_file=FALSE;
}
snprintf(out_path,sizeof(out_path)-1,"%s/%s",qdir,newtic->file);
snprintf(xlo_str,sizeof(xlo_str)-1,"^%s",out_path);
if(ln(previous_file,out_path))
if(ln(in_path,out_path))
{
if(acur->flags & AREA_PASSTHRU)
{
freetic(newtic);
tlcur->bad=TRUE;
mk_badname(tlcur);
l_printf("BADTIC: tic=%s, xlo=%s, unable to link file %s to %s,"
"area %s is passthru",
tlcur->name,xlo,xlo_str,in_path,out_path,acur->name);
break;
}
snprintf(xlo_str,sizeof(xlo_str)-1,"%s/%s",acur->path,newtic->file);
}
strcpy(previous_file,out_path);
}
/* write file's path to xlo */
if(write_to_xlo(xlo,xlo_str[0]=='^'?xlo_str+1:xlo_str,xlo_str[0]=='^',
bsy,mk_bsy))
{
freetic(newtic);
tlcur->bad=TRUE;
mk_badname(tlcur);
l_printf("BADTIC: tic=%s, xlo=%s, unable to write to xlo [%s]",
tlcur->name,xlo,xlo_str);
break;
}
/* write to xlo path_to_tic, ftmp is a tic's name */
if(write_to_xlo(xlo,ftmp,TRUE,bsy,mk_bsy))
{
freetic(newtic);
tlcur->bad=TRUE;
mk_badname(tlcur);
l_printf("BADTIC: tic=%s, xlo=%s, unable to write to xlo [%s]",
tlcur->name,xlo,ftmp);
break;
}
l_printf("OK: area=%s, file=%s, node=%s",newtic->area,newtic->file,
nodetoftn(NULL,&(utmp->addr)));
freetic(newtic);
}
/* if current area is "passthru", delete file from inbound */
if(acur->flags & AREA_PASSTHRU)
{
snprintf(in_path,sizeof(in_path)-1,"%s/%s",inbound,tic->realname);
if(remove(in_path))
l_printf("ERROR: unable to delete file %s",in_path);
}
}
}
void find_bad_tics(void)
/* find bad tics */
{
char buff[PATH_MAX],node_buff[FTN_MAX_SIZE]; area_t *atmp;
struct stat stat_buf; user_t *user_cur;
int i; tic_t *cur; ticlist_t *tlcur; unsigned long tmp_crc32;
/* printf("DEBUG: ticlist_list_max=%d\n",ticlist_list_max); */
for(i=0;i<ticlist_list_max;i++)
{
tlcur=ilist_find_entry(ticlist_list,i);
ass(tlcur!=NULL);
if(tlcur->bad==TRUE)
{
mk_badname(tlcur);
continue;
}
cur=tlcur->tic;
ass(cur!=NULL);
nodetoftn(node_buff,&(cur->from));
user_cur=list_find_entry(users,node_buff);
/* check for file existing */
/* TODO: fullname support here */
if(find_file(tlcur->path,buff,cur->file,cur->crc,cur->size))
{
/* TODO: old_tic check! */
l_printf("BADTIC: ticname=%s, file %s not found "
"(maybe incorrect crc32 or size, not found by find_file() )",
tlcur->name,cur->file);
tlcur->bad=1;
tlcur->old_tic=OLDTIC_KEEP;
continue;
}
cur->realname=xstrcpy(buff);
/* check for node existing */
if(!user_cur)
{
l_printf("BADTIC: ticname=%s, area %s, file %s - node %s unknown",
tlcur->name,cur->area,cur->file,node_buff);
tlcur->bad=1;
continue;
}
/* check for password (TODO: maybe add check from_pwd) */
if(strcasecmp(user_cur->passwd,cur->pw))
{
l_printf("BADTIC: ticname=%s, area %s, node %s - INCORRECT password",
tlcur->name,cur->area,node_buff);
tlcur->bad=1;
continue;
}
snprintf(buff,sizeof(buff)-1,"%s/%s",tlcur->path,cur->realname);
/* printf("DEBUG: file_name=%s\n",buff); */
if(stat(buff,&stat_buf))
{
l_printf("BADTIC: ticname=%s, stat() failed for file %s",
tlcur->name,cur->file);
tlcur->bad=1;
mk_badname(tlcur);
continue;
}
/* check for file size, if tic_size==-1, don't check */
if(cur->size!=(unsigned long)(-1) && stat_buf.st_size!=cur->size)
{
l_printf("BADTIC: ticname=%s, invalid SIZE in file %s (got %lu, need %lu)",
tlcur->name,cur->file,stat_buf.st_size,cur->size);
tlcur->bad=1;
mk_badname(tlcur);
continue;
}
/* check for crc32 */
if(crc32_ignore==0)
if(cur->crc!=(tmp_crc32=filecrc32(buff)))
{
l_printf("BADTIC: ticname=%s, invalid CRC32 in file %s"
"(got %lX, need %lX)",tlcur->name,cur->file,tmp_crc32,cur->crc);
tlcur->bad=1;
mk_badname(tlcur);
continue;
}
/* check for area existing */
if(!list_find(areas,cur->area))
{
l_printf("BADTIC: ticname=%s, area=%s - not-existing area",
tlcur->name,cur->area);
if(user_cur->flags & USER_AUTOCREATE)
{
l_printf("BADTIC: area %s passed to autocreate",cur->area);
list_add(newareas_descs,cur->area,cur->areadesc?cur->areadesc:"");
list_add(newareas_users,cur->area,user_cur);
}
tlcur->bad=1;
continue;
}
/* check for node is exist and not-readonly for this area */
/* find from area_t->users by key=ftn_node_string (without ! in 1st pos) */
atmp=list_find_entry(areas,cur->area);
ass(atmp!=NULL);
/* assume local address (aka or whoami) connected without checking */
if( ! ( nodecmp(&(cur->from),&whoami)==0 ||
(atmp->aka && nodecmp(&(cur->from),atmp->aka))==0 )
)
{
user_cur=list_find_entry(atmp->users,node_buff);
/* TODO: maybe make report for readonly node here */
if(!user_cur)
{
l_printf(
"BADTIC: tic=%s, file %s, node %s r/o or not exist for area %s",
tlcur->name,cur->file,node_buff,cur->area);
tlcur->bad=1;
continue;
}
/* check for group validation */
if(!validate_group(atmp,user_cur))
{
l_printf(
"BADTIC: tic=%s, file %s, node %s, area %s don't have group %s.",
tlcur->name,cur->file,node_buff,cur->area,atmp->group);
tlcur->bad=1;
continue;
}
}
/* printf("*** %p,%p\n",tlcur->name,cur->realname); */
l_printf("TIC_OK: name=%s, file=%s",tlcur->name,cur->realname);
}
}
void move_bad_tics(void)
/* move bad tics to bad_dir and delete if old_tic=OLDTIC_REMOVE */
{
char buff[PATH_MAX],buff2[PATH_MAX];
int i; tic_t *cur; ticlist_t *tlcur;
for(i=0;i<ticlist_list_max;i++)
{
tlcur=ilist_find_entry(ticlist_list,i);
ass(tlcur!=NULL);
cur=tlcur->tic;
ass(cur!=NULL);
if(tlcur->bad==FALSE) continue;
if(tlcur->old_tic==OLDTIC_REMOVE)
{
snprintf(buff,sizeof(buff)-1,"%s/%s",tlcur->path,tlcur->name);
if(remove(buff))
l_printf("unable to delete old tic %s",buff);
continue;
}
if(tlcur->type==TICLIST_BADDIR && tlcur->badname==NULL) continue;
if(tlcur->old_tic==OLDTIC_KEEP) continue;
mkdirs(bad_dir,bad_dir_mode);
/* move tic file */
snprintf(buff,sizeof(buff)-1,"%s/%s",tlcur->path,tlcur->name);
snprintf(buff2,sizeof(buff2)-1,"%s/%s",
bad_dir,tlcur->badname?tlcur->badname:tlcur->name);
if(mv(buff,buff2))
{
l_printf("unable to move %s to %s",buff,buff2);
}
/* move file (is tic_t->realname != NULL) */
/* fprintf(stderr,"DEBUG: %s %s\n",cur->file,cur->realname); */
if(cur->realname)
{
snprintf(buff,sizeof(buff)-1,"%s/%s",tlcur->path,cur->realname);
snprintf(buff2,sizeof(buff2)-1,"%s/%s",bad_dir,cur->realname);
if(mv(buff,buff2))
{
l_printf("unable to move %s to %s",buff,buff2);
}
}
}
}
void create_new_areas(void)
{
int i,child_pid,w,j; list_t *tmp_d,*tmp_u; char *a1,*a2;
char node_buff[FTN_MAX_SIZE]; user_t *tmp_usert;
char buff[BUFSIZE],node_buff2[FTN_MAX_SIZE];
for(i=0;i<list_head_max(newareas_descs/*same as newareas_users*/);i++)
{
tmp_d=list_get(newareas_descs,i); tmp_u=list_get(newareas_users,i);
ass(tmp_d!=NULL && tmp_u!=NULL);
if(list_entry(tmp_d))
if(*((char*)list_entry(tmp_d))!=0)
{
/* printf("!%s!\n",(char*)list_entry(tmp_d)); */
setenv("newarea_desc",list_entry(tmp_d),1);
}
a1=list_key(tmp_d); a2=node_buff;
tmp_usert=list_entry(tmp_u);
nodetoftn(node_buff,&(tmp_usert->addr));
/* Dangerous: maybe need dynamically allocated buffer for
$autoconnected_users */
/* auto_ro имеет больший приоритет, чем auto_rw */
buff[0]=0;
for(j=0;j<list_head_max(users);j++)
{
user_t *tmpu; list_t *tmpl;
tmpl=list_get(users,j);
ass(tmpl!=NULL);
tmpu=list_entry(tmpl);
ass(tmpu!=NULL);
if((tmpu->flags & USER_AUTO_RW) || (tmpu->flags & USER_AUTO_RO))
{
strcpy(node_buff2," !");
nodetoftn(&node_buff2[(tmpu->flags & USER_AUTO_RO)?2:1],&(tmpu->addr));
strcat(buff,node_buff2);
}
}
/* printf("DEBUG: %s\n",buff); */
if(buff[0]!=0) setenv("autoconnected_users",buff,1);
child_pid=fork();
if(child_pid==0)
{
/* exec external autocreator */
swap_uid_gid();
execl(newarea_exec,newarea_exec,a1,a2,NULL);
e_printf("exec of newarea_exec \"%s\" failed",newarea_exec);
exit(0);
}
else if(child_pid==-1)
{
e_printf("fork() for newarea_exec failed");
}
else
{
while(1)
{
w=wait(NULL);
if(w==0 || w==-1) break;
}
}
}
}
void toss_tics(void)
/*
move files to fileechos, mark tics with unmovable files as bad
*/
{
char oldname[PATH_MAX],newname[PATH_MAX],buff[BUFSIZE],*p;
FILE *fp,*fp2,*announce_f=NULL,*private_a_f;
int i,j; tic_t *cur; ticlist_t *tlcur; area_t *curarea;
for(i=0;i<ticlist_list_max;i++)
{
tlcur=ilist_find_entry(ticlist_list,i);
ass(tlcur!=NULL);
cur=tlcur->tic;
ass(cur!=NULL);
if(tlcur->bad==TRUE) continue;
curarea=list_find_entry(areas,cur->area);
ass(curarea!=NULL);
/* skip file if area is "passthru" */
if(curarea->flags & AREA_PASSTHRU) continue;
/*
printf("DEBUG: cur=%p\n",cur);
printf("DBG: %p\n",cur->replaces);
printf("DBG: %s\n",cur->replaces?cur->replaces:"(NULL)");
*/
/* process "Replaces" keyword */
if(cur->replaces)
{
char *tmp1,*tmp2;
if( ! (curarea->flags & AREA_NO_REPLACES) )
{
if( check_replaces(cur->file,cur->replaces) == FALSE )
{
/* attempt to hack with "Replaces" */
l_printf("BADTIC: %s: attempt to hack with \"Replaces\" (%s,%s)",
tlcur->name,cur->file,cur->replaces);
tlcur->bad=1;
mk_badname(tlcur);
continue;
}
}
else
{
/* insecure replaces check */
if(strchr("[]*?",cur->replaces[0]))
{
/* attempt to hack with "Replaces" (2, small security) */
l_printf("BADTIC: %s: attempt to hack with \"Replaces\" (2) (%s,%s)",
tlcur->name,cur->file,cur->replaces);
tlcur->bad=1;
mk_badname(tlcur);
continue;
}
}
ass(curarea->path!=NULL);
rm_by_mask(curarea->path,cur->replaces);
tmp1=xstrcpy(cur->replaces);
tmp1=xstrcat(tmp1,".desc");
if(strchr(desc_dir,'/'))
{
tmp2=xstrcpy(desc_dir);
}
else
{
tmp2=xstrcpy(curarea->path);
tmp2=xstrcat(tmp2,"/");
tmp2=xstrcat(tmp2,desc_dir);
}
/* printf("DEBUG: tmp2=%s, tmp1=%s\n",tmp2,tmp1); */
rm_by_mask(tmp2,tmp1);
xfree(tmp1);
xfree(tmp2);
}
mkdirs(curarea->path,dirmode(curarea->mode==-1?file_mode:curarea->mode));
snprintf(oldname,sizeof(oldname)-1,"%s/%s",tlcur->path,cur->realname);
snprintf(newname,sizeof(newname)-1,"%s/%s",curarea->path,cur->file);
if(mv(oldname,newname))
{
l_printf("BADTIC: unable to move file %s from %s/ to %s/",
cur->realname,tlcur->path,curarea->path);
tlcur->bad=1;
mk_badname(tlcur);
continue;
}
chmod(newname,curarea->mode==-1?file_mode:curarea->mode);
/* write desc_file and "newfile" file only cur->desc and cur->ldesc */
/* skip announce_exec call if area is AREA_NOANNOUNCE */
if(cur->desc==NULL && cur->ldesc==NULL) continue;
if(strchr(desc_dir,'/'))
{
strcpy(newname,desc_dir);
mkdirs(newname,dirmode(curarea->mode==-1?file_mode:curarea->mode));
snprintf(newname,sizeof(newname)-1,"%s/%s.desc",desc_dir,cur->file);
}
else
{
snprintf(newname,sizeof(newname)-1,"%s/%s",curarea->path,desc_dir);
mkdirs(newname,dirmode(curarea->mode==-1?file_mode:curarea->mode));
snprintf(newname,sizeof(newname)-1,"%s/%s/%s.desc",
curarea->path,desc_dir,cur->file);
}
private_a_f=NULL;
/* skip .desc if curarea has "no_desc" option */
if( ! (curarea->flags & AREA_NO_DESC) )
fp=fopen(newname,"w");
fp2=fopen(curarea->newfile?curarea->newfile:default_newfile,"a");
ass(announce_exec!=NULL);
if( ! (curarea->flags & AREA_NOANNOUNCE) )
if(announce_exec[0]!=0 && announce_f==NULL)
{
char buff[PATH_MAX];
/* TODO: maybe some security check here */
if(curarea->flags & AREA_PRIVATE_ANNOUNCE)
if(curarea->group)
{
snprintf(buff,sizeof(buff)-1,"%s.%s",announce_exec,curarea->group);
swap_uid_gid();
private_a_f=popen(buff,"w");
swap_uid_gid();
}
swap_uid_gid();
announce_f=popen(announce_exec,"w");
swap_uid_gid();
if(announce_f) fprintf(announce_f,"\n");
}
if(fp2)
{
fprintf(fp2,"AREA: %-15s FILE: %s\n",curarea->name,cur->file);
if(pub_path && pub_url &&
strlen(curarea->path)>=strlen(pub_path) &&
strncmp(curarea->path,pub_path,strlen(pub_path))==0)
{
fprintf(fp2,"URL: %s%s/%s\n",pub_url,
curarea->path+strlen(pub_path),cur->file);
}
}
if(announce_f)
{
fprintf(announce_f,">AREA: %-15s FILE: %s\n",curarea->name,cur->file);
if(pub_path && pub_url &&
strlen(curarea->path)>=strlen(pub_path) &&
strncmp(curarea->path,pub_path,strlen(pub_path))==0)
{
fprintf(announce_f,"URL: %s%s/%s\n",pub_url,
curarea->path+strlen(pub_path),cur->file);
}
}
for(j=0;j<cur->max_desc;j++)
{
p=ilist_find_entry(cur->desc,j);
ass(p!=NULL);
strcpy(buff,p);
a2k(buff,strlen(buff));
if(fp)
fprintf(fp,"%s\n",buff);
if(fp2)
fprintf(fp2,"%s\n",buff);
if(announce_f)
fprintf(announce_f,"%s\n",buff);
}
for(j=0;j<cur->max_ldesc;j++)
{
p=ilist_find_entry(cur->ldesc,j);
ass(p!=NULL);
strcpy(buff,p);
a2k(buff,strlen(buff));
if(fp)
fprintf(fp,"%s\n",buff);
if(fp2)
fprintf(fp2,"%s\n",buff);
if(announce_f)
fprintf(announce_f,"%s\n",buff);
}
if(fp2) fprintf(fp2,"\n");
if(announce_f) fprintf(announce_f,"\n");
if(fp) fclose(fp);
if(fp2) fclose(fp2);
if(private_a_f) fclose(private_a_f);
}
if(announce_f) pclose(announce_f);
}
void remove_good_tics(void)
/* remove all of good tics after tossing and creating outbound */
{
char name[PATH_MAX]; int i; ticlist_t *tlcur;
for(i=0;i<ticlist_list_max;i++)
{
tlcur=ilist_find_entry(ticlist_list,i);
ass(tlcur!=NULL);
if(tlcur->bad==TRUE) continue; /* remove only good tics */
snprintf(name,sizeof(name)-1,"%s/%s",tlcur->path,tlcur->name);
if(remove(name))
{
l_printf("BADTIC: ticname=%s, unable to delete good tic (file is ok)",
tlcur->name);
tlcur->bad=1;
mk_badname(tlcur);
continue;
}
}
}
void toss(void)
{
newareas_descs=list_init();
newareas_users=list_init();
process_gtic_q();
find_bad_tics();
toss_tics();
create_outbound();
remove_good_tics();
move_bad_tics();
if(newarea_exec!=NULL)
if(newarea_exec[0]!=0)
create_new_areas();
list_free(newareas_descs);
list_free(newareas_users);
}
syntax highlighted by Code2HTML, v. 0.9.1