/* tossing functions */ #include #include #include #include #include #include #include #include #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;igroups);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;igroups);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;id_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;ibad==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;jusers);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;kusers);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;ibad==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;itic; 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;iaddr)); /* Dangerous: maybe need dynamically allocated buffer for $autoconnected_users */ /* auto_ro имеет больший приоритет, чем auto_rw */ buff[0]=0; for(j=0;jflags & 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;itic; 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;jmax_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;jmax_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;ibad==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); }