Commit 11e529d4 authored by rswindell's avatar rswindell
Browse files

* Implemented support for new LIB_DIRS option:

  Automatically detect child sub-directories and make them available as virtual
  directories for users to download from - only useful via FTP currently.
* Implemented Sorting options for Message Groups and File Libraries:
  Sub-boards within groups and directories within library can now be
  automatically sorted based on the sysop's chosen sort field (long name, short
  name, or internal code)
  - Required that sub-boards are now stored/saved in msgs.cnf based on groups
  - Required QWKnet hub sub-board reference dynamic renumbering
* Implemented "Template" toggle option for sub-boards and file directories:
  A sub-board or directory marked as "template" will be used for newly created
  (or imported) subs/dirs for that group/lib. Clone Options via SCFG will now
  use the "template" item as the source of the cloned settings, if available.
parent 66ae43ca
/* load_cfg.c */
/* Synchronet configuration load routines (exported) */
/* $Id$ */
......@@ -139,13 +137,6 @@ void prep_cfg(scfg_t* cfg)
{
int i;
#if 0 /* def __unix__ */
strlwr(cfg->text_dir); /* temporary Unix-compatibility hack */
strlwr(cfg->temp_dir); /* temporary Unix-compatibility hack */
strlwr(cfg->data_dir); /* temporary Unix-compatibility hack */
strlwr(cfg->exec_dir); /* temporary Unix-compatibility hack */
#endif
/* Fix-up paths */
prep_dir(cfg->ctrl_dir, cfg->data_dir, sizeof(cfg->data_dir));
prep_dir(cfg->ctrl_dir, cfg->logs_dir, sizeof(cfg->logs_dir));
......@@ -161,17 +152,6 @@ void prep_cfg(scfg_t* cfg)
prep_path(cfg->echomail_sem);
prep_path(cfg->inetmail_sem);
#if 0 /* def __unix__ */
/* temporary hack for Unix compatibility */
strlwr(cfg->logon_mod);
strlwr(cfg->logoff_mod);
strlwr(cfg->newuser_mod);
strlwr(cfg->login_mod);
strlwr(cfg->logout_mod);
strlwr(cfg->sync_mod);
strlwr(cfg->expire_mod);
#endif
for(i=0;i<cfg->total_subs;i++) {
if(!cfg->sub[i]->data_dir[0]) /* no data storage path specified */
......@@ -224,6 +204,48 @@ void prep_cfg(scfg_t* cfg)
prep_path(cfg->dir[i]->upload_sem);
}
for(i=0;i<cfg->total_libs;i++) {
if((cfg->lib[i]->misc&LIB_DIRS) == 0 || cfg->lib[i]->parent_path[0] == 0)
continue;
char path[MAX_PATH+1];
SAFECOPY(path, cfg->lib[i]->parent_path);
backslash(path);
strcat(path, ALLFILES);
glob_t g;
if(glob(path, GLOB_MARK, NULL, &g))
continue;
for(uint gi=0;gi<g.gl_pathc;gi++) {
char* p = g.gl_pathv[gi];
char* tp = lastchar(p);
if(*tp != '/')
continue;
*tp = 0;
dir_t dir;
memset(&dir, 0, sizeof(dir));
dir.lib = i;
dir.misc = DIR_FILES;
SAFECOPY(dir.path, p);
backslash(dir.path);
SAFECOPY(dir.lname, getfname(p));
SAFECOPY(dir.sname, dir.lname);
char code_suffix[LEN_EXTCODE+1];
SAFECOPY(code_suffix, dir.lname);
prep_code(code_suffix, cfg->lib[i]->code_prefix);
SAFECOPY(dir.code_suffix, code_suffix);
SAFEPRINTF2(dir.code,"%s%s"
,cfg->lib[i]->code_prefix
,dir.code_suffix);
dir_t** new_dirs;
if((new_dirs=(dir_t **)realloc(cfg->dir, sizeof(dir_t *)*(cfg->total_dirs+2)))==NULL)
continue;
cfg->dir = new_dirs;
if((cfg->dir[cfg->total_dirs] = malloc(sizeof(dir_t))) == NULL)
continue;
*cfg->dir[cfg->total_dirs++] = dir;
}
}
/* make data filenames are all lowercase */
for(i=0;i<cfg->total_shells;i++)
......@@ -404,6 +426,35 @@ char* prep_path(char* path)
return(path);
}
/* Prepare a string to be used as an internal code */
/* Return the usable code */
char* prep_code(char *str, const char* prefix)
{
char tmp[1024];
int i,j;
if(prefix!=NULL) { /* skip the grp/lib prefix, if specified */
i=strlen(prefix);
if(i && strnicmp(str,prefix,i)==0 && strlen(str)!=i)
str+=i;
}
for(i=j=0;str[i] && i<sizeof(tmp);i++)
if(str[i]>' ' && !(str[i]&0x80) && str[i]!='*' && str[i]!='?'
&& strchr(ILLEGAL_FILENAME_CHARS,str[i])==NULL)
tmp[j++]=toupper(str[i]);
tmp[j]=0;
strcpy(str,tmp);
if(j>LEN_CODE) { /* Extra chars? Strip symbolic chars */
for(i=j=0;str[i];i++)
if(isalnum(str[i]))
tmp[j++]=str[i];
tmp[j]=0;
strcpy(str,tmp);
}
str[LEN_CODE]=0;
return(str);
}
/****************************************************************************/
/* Auto-toggle daylight savings time in US time-zones */
/****************************************************************************/
......
......@@ -2724,10 +2724,10 @@ void event_thread(void* arg)
,sbbs->cfg.data_dir,sbbs->cfg.qhub[i]->id);
file=sbbs->nopen(str,O_RDONLY);
for(j=0;j<sbbs->cfg.qhub[i]->subs;j++) {
sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]].ptr=0;
sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]->subnum].ptr=0;
if(file!=-1) {
lseek(file,sbbs->cfg.sub[sbbs->cfg.qhub[i]->sub[j]]->ptridx*sizeof(int32_t),SEEK_SET);
read(file,&sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]].ptr,sizeof(sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]].ptr));
lseek(file,sbbs->cfg.sub[sbbs->cfg.qhub[i]->sub[j]->subnum]->ptridx*sizeof(int32_t),SEEK_SET);
read(file,&sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]->subnum].ptr,sizeof(sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]->subnum].ptr));
}
}
if(file!=-1)
......@@ -2741,14 +2741,14 @@ void event_thread(void* arg)
else {
for(j=l=0;j<sbbs->cfg.qhub[i]->subs;j++) {
while(filelength(file)<
sbbs->cfg.sub[sbbs->cfg.qhub[i]->sub[j]]->ptridx*4L) {
sbbs->cfg.sub[sbbs->cfg.qhub[i]->sub[j]->subnum]->ptridx*4L) {
l32=l;
write(file,&l32,4); /* initialize ptrs to null */
}
lseek(file
,sbbs->cfg.sub[sbbs->cfg.qhub[i]->sub[j]]->ptridx*sizeof(int32_t)
,sbbs->cfg.sub[sbbs->cfg.qhub[i]->sub[j]->subnum]->ptridx*sizeof(int32_t)
,SEEK_SET);
write(file,&sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]].ptr,sizeof(sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]].ptr));
write(file,&sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]->subnum].ptr,sizeof(sbbs->subscan[sbbs->cfg.qhub[i]->sub[j]->subnum].ptr));
}
close(file);
}
......
......@@ -165,7 +165,7 @@ bool sbbs_t::pack_rep(uint hubnum)
free(mail);
for(i=0;i<cfg.qhub[hubnum]->subs;i++) {
j=cfg.qhub[hubnum]->sub[i]; /* j now equals the real sub num */
j=cfg.qhub[hubnum]->sub[i]->subnum; /* j now equals the real sub num */
msgs=getlastmsg(j,&last,0);
lncntr=0; /* defeat pause */
if(!msgs || last<=subscan[j].ptr) {
......
......@@ -1016,7 +1016,7 @@ uint sbbs_t::resolve_qwkconf(uint n, int hubnum)
if(hubnum >= 0 && hubnum < cfg.total_qhubs) {
for(j=0;j<cfg.qhub[hubnum]->subs;j++)
if(cfg.qhub[hubnum]->conf[j] == n)
return cfg.qhub[hubnum]->sub[j];
return cfg.qhub[hubnum]->sub[j]->subnum;
return INVALID_SUB;
}
......
......@@ -1083,6 +1083,7 @@ extern "C" {
DLLEXPORT void DLLCALL free_cfg(scfg_t* cfg);
DLLEXPORT void DLLCALL free_text(char* text[]);
DLLEXPORT ushort DLLCALL sys_timezone(scfg_t* cfg);
DLLEXPORT char * DLLCALL prep_dir(const char* base, char* dir, size_t buflen);
/* scfgsave.c */
DLLEXPORT BOOL DLLCALL save_cfg(scfg_t* cfg, int backup_level);
......@@ -1098,9 +1099,6 @@ extern "C" {
DLLEXPORT void DLLCALL refresh_cfg(scfg_t* cfg);
/* scfglib1.c */
DLLEXPORT char * DLLCALL prep_dir(const char* base, char* dir, size_t buflen);
/* logfile.cpp */
DLLEXPORT int DLLCALL errorlog(scfg_t* cfg, const char* host, const char* text);
......@@ -1316,6 +1314,7 @@ int strsame(const char *str1, const char *str2); /* Compares number of same cha
/* load_cfg.c */
BOOL md(char *path);
char* prep_code(char *str, const char* prefix);
#ifdef SBBS /* These aren't exported */
......
......@@ -220,6 +220,7 @@ typedef struct js_callback {
/* Bit values for sub[x].misc */
#define SUB_NOVOTING (1L<<0) /* No voting allowed in this sub-board */
#define SUB_TEMPLATE (1L<<1) /* Use this sub as template for new subs (in this group) */
#define SUB_QNET (1L<<3) /* Sub-board is netted via QWK network */
#define SUB_PNET (1L<<4) /* Sub-board is netted via PostLink */
#define SUB_FIDO (1L<<5) /* Sub-board is netted via FidoNet */
......@@ -250,28 +251,32 @@ typedef struct js_callback {
#define SUB_NOUSERSIG (1L<<30) /* Suppress user signatures */
#define SUB_HDRMOD (1L<<31) /* Modified sub-board header info (SCFG) */
/* Bit values for lib[x].misc */
#define LIB_DIRS (1<<0) /* Local directory (sub-directory of lib parent) access */
/* Bit values for dir[x].misc */
#define DIR_FCHK (1<<0) /* Check for file existence */
#define DIR_RATE (1<<1) /* Force uploads to be rated G,R, or X */
#define DIR_MULT (1<<2) /* Ask for multi-disk numbering */
#define DIR_DUPES (1<<3) /* Search this dir for upload dupes */
#define DIR_FREE (1<<4) /* Free downloads */
#define DIR_TFREE (1<<5) /* Time to download is free */
#define DIR_CDTUL (1<<6) /* Credit Uploads */
#define DIR_CDTDL (1<<7) /* Credit Downloads */
#define DIR_ANON (1<<8) /* Anonymous uploads */
#define DIR_AONLY (1<<9) /* Anonymous only */
#define DIR_ULDATE (1<<10) /* Include upload date in listing */
#define DIR_DIZ (1<<11) /* FILE_ID.DIZ and DESC.SDI support */
#define DIR_NOSCAN (1<<12) /* Don't new-scan this directory */
#define DIR_NOAUTO (1<<13) /* Don't auto-add this directory */
#define DIR_ULTIME (1<<14) /* Deduct time during uploads */
#define DIR_CDTMIN (1<<15) /* Give uploader minutes instead of cdt */
#define DIR_SINCEDL (1<<16) /* Purge based on days since last dl */
#define DIR_MOVENEW (1<<17) /* Files marked as new when moved */
#define DIR_QUIET (1<<18) /* Do not notify uploader of downloads */
#define DIR_NOSTAT (1<<19) /* Do not include transfers in system stats */
#define DIR_FILES (1<<20) /* List/access files not in database */
#define DIR_FCHK (1<<0) /* Check for file existence */
#define DIR_RATE (1<<1) /* Force uploads to be rated G,R, or X */
#define DIR_MULT (1<<2) /* Ask for multi-disk numbering */
#define DIR_DUPES (1<<3) /* Search this dir for upload dupes */
#define DIR_FREE (1<<4) /* Free downloads */
#define DIR_TFREE (1<<5) /* Time to download is free */
#define DIR_CDTUL (1<<6) /* Credit Uploads */
#define DIR_CDTDL (1<<7) /* Credit Downloads */
#define DIR_ANON (1<<8) /* Anonymous uploads */
#define DIR_AONLY (1<<9) /* Anonymous only */
#define DIR_ULDATE (1<<10) /* Include upload date in listing */
#define DIR_DIZ (1<<11) /* FILE_ID.DIZ and DESC.SDI support */
#define DIR_NOSCAN (1<<12) /* Don't new-scan this directory */
#define DIR_NOAUTO (1<<13) /* Don't auto-add this directory */
#define DIR_ULTIME (1<<14) /* Deduct time during uploads */
#define DIR_CDTMIN (1<<15) /* Give uploader minutes instead of cdt */
#define DIR_SINCEDL (1<<16) /* Purge based on days since last dl */
#define DIR_MOVENEW (1<<17) /* Files marked as new when moved */
#define DIR_QUIET (1<<18) /* Do not notify uploader of downloads */
#define DIR_NOSTAT (1<<19) /* Do not include transfers in system stats */
#define DIR_FILES (1<<20) /* List/access files not in database */
#define DIR_TEMPLATE (1<<21) /* Use this dir as template for new dirs (in this lib) */
/* Bit values for file_t.misc */
#define FM_EXTDESC (1<<0) /* Extended description exists */
......@@ -310,6 +315,14 @@ enum { /* Values for dir[x].sort */
,SORT_DATE_D /* Sort by upload date, descending */
};
/* Values for grp[x].sort */
enum area_sort {
AREA_SORT_NONE,
AREA_SORT_LNAME,
AREA_SORT_SNAME,
AREA_SORT_CODE,
};
enum {
clr_mnehigh
,clr_mnelow
......
......@@ -41,8 +41,8 @@
typedef struct { /* Message sub board info */
char code[LEN_EXTCODE+1]; /* Internal code (with optional lib prefix) */
char code_suffix[LEN_CODE+1]; /* Eight character code suffix */
char lname[LEN_SLNAME+1], /* Short name - used for prompts */
sname[LEN_SSNAME+1], /* Long name - used for listing */
char lname[LEN_SLNAME+1], /* Long name - used for listing */
sname[LEN_SSNAME+1], /* Short name - used for prompts */
arstr[LEN_ARSTR+1], /* Access requirements */
read_arstr[LEN_ARSTR+1], /* Read requirements */
post_arstr[LEN_ARSTR+1], /* Post requirements */
......@@ -62,7 +62,8 @@ typedef struct { /* Message sub board info */
uint16_t grp, /* Which group this sub belongs to */
ptridx, /* Index into pointer file */
qwkconf, /* QWK conference number */
maxage; /* Max age of messages (in days) */
maxage, /* Max age of messages (in days) */
subnum; /* ephemeral index of this sub in cfg.sub[] */
uint32_t misc, /* Miscellaneous flags */
maxmsgs, /* Max number of messages allowed */
maxcrcs; /* Max number of CRCs to keep */
......@@ -71,19 +72,20 @@ typedef struct { /* Message sub board info */
} sub_t;
typedef struct { /* Message group info */
char lname[LEN_GLNAME+1], /* Short name */
sname[LEN_GSNAME+1], /* Long name */
char lname[LEN_GLNAME+1], /* Long name */
sname[LEN_GSNAME+1], /* Short name */
arstr[LEN_ARSTR+1], /* Access requirements */
code_prefix[LEN_CODE+1]; /* Prefix for internal code */
uchar *ar;
enum area_sort sort;
} grp_t;
typedef struct { /* Transfer Directory Info */
char code[LEN_EXTCODE+1]; /* Internal code (with optional lib prefix) */
char code_suffix[LEN_CODE+1]; /* Eight character code suffix */
char lname[LEN_SLNAME+1], /* Short name - used for prompts */
sname[LEN_SSNAME+1], /* Long name - used for listing */
char lname[LEN_SLNAME+1], /* Long name - used for listing */
sname[LEN_SSNAME+1], /* Short name - used for prompts */
arstr[LEN_ARSTR+1], /* Access Requirements */
ul_arstr[LEN_ARSTR+1], /* Upload Requirements */
dl_arstr[LEN_ARSTR+1], /* Download Requirements */
......@@ -104,19 +106,22 @@ typedef struct { /* Transfer Directory Info */
maxage, /* Max age of files (in days) */
up_pct, /* Percentage of credits on uloads */
dn_pct, /* Percentage of credits on dloads */
lib; /* Which library this dir is in */
lib, /* Which library this dir is in */
dirnum; /* ephemeral index of this dir in cfg.dir[] */
uint32_t misc; /* Miscellaneous bits */
} dir_t;
typedef struct { /* Transfer Library Information */
char lname[LEN_GLNAME+1], /* Short Name - used for prompts */
sname[LEN_GSNAME+1], /* Long Name - used for listings */
char lname[LEN_GLNAME+1], /* Long Name - used for listings */
sname[LEN_GSNAME+1], /* Short Name - used for prompts */
arstr[LEN_ARSTR+1], /* Access Requirements */
code_prefix[LEN_CODE+1], /* Prefix for internal code */
parent_path[48]; /* Parent for dir paths */
uchar *ar;
uint32_t offline_dir; /* Offline file directory */
uint32_t misc; /* Miscellaneous bits */
enum area_sort sort;
} lib_t;
......@@ -313,7 +318,7 @@ typedef struct { /* QWK Network Hub */
freq, /* Frequency of call-outs */
subs, /* Number Sub-boards carried */
*conf; /* Conference number of ea. */
ulong *sub; /* Number of local sub-board for ea. */
sub_t** sub;
time32_t last; /* Last network attempt */
uint32_t misc; /* QHUB_* flags */
......
......@@ -475,9 +475,10 @@ BOOL read_msgs_cfg(scfg_t* cfg, char* error)
get_str(cfg->grp[i]->code_prefix,instream);
get_int(c,instream);
cfg->grp[i]->sort = c;
for(j=0;j<43;j++)
get_int(n,instream);
}
}
cfg->total_grps=i;
/**********************/
......@@ -498,6 +499,8 @@ BOOL read_msgs_cfg(scfg_t* cfg, char* error)
return allocerr(instream,error,offset,fname,sizeof(sub_t));
memset(cfg->sub[i],0,sizeof(sub_t));
cfg->sub[i]->subnum = i;
get_int(cfg->sub[i]->grp,instream);
get_str(cfg->sub[i]->lname,instream);
get_str(cfg->sub[i]->sname,instream);
......@@ -625,7 +628,7 @@ BOOL read_msgs_cfg(scfg_t* cfg, char* error)
get_int(k,instream);
if(k) {
if((cfg->qhub[i]->sub=(ulong *)malloc(sizeof(ulong)*k))==NULL)
if((cfg->qhub[i]->sub=(sub_t**)malloc(sizeof(sub_t*)*k))==NULL)
return allocerr(instream,error,offset,fname,sizeof(ulong)*k);
if((cfg->qhub[i]->conf=(ushort *)malloc(sizeof(ushort)*k))==NULL)
return allocerr(instream,error,offset,fname,sizeof(ushort)*k);
......@@ -634,18 +637,20 @@ BOOL read_msgs_cfg(scfg_t* cfg, char* error)
}
for(j=0;j<k;j++) {
uint16_t confnum;
uint16_t subnum;
uint8_t mode;
if(feof(instream)) break;
get_int(cfg->qhub[i]->conf[cfg->qhub[i]->subs],instream);
get_int(subnum,instream);
cfg->qhub[i]->sub[cfg->qhub[i]->subs]=subnum;
get_int(cfg->qhub[i]->mode[cfg->qhub[i]->subs],instream);
if(cfg->qhub[i]->sub[cfg->qhub[i]->subs]<cfg->total_subs)
cfg->sub[cfg->qhub[i]->sub[cfg->qhub[i]->subs]]->misc|=SUB_QNET;
else
continue;
if(cfg->qhub[i]->sub[cfg->qhub[i]->subs]!=INVALID_SUB)
get_int(confnum,instream);
get_int(subnum, instream);
get_int(mode, instream);
if(subnum < cfg->total_subs) {
cfg->sub[subnum]->misc |= SUB_QNET;
cfg->qhub[i]->sub[cfg->qhub[i]->subs] = cfg->sub[subnum];
cfg->qhub[i]->mode[cfg->qhub[i]->subs] = mode;
cfg->qhub[i]->conf[cfg->qhub[i]->subs] = confnum;
cfg->qhub[i]->subs++;
}
}
get_int(cfg->qhub[i]->misc, instream);
for(j=0;j<30;j++)
......
......@@ -310,8 +310,11 @@ BOOL read_file_cfg(scfg_t* cfg, char* error)
get_str(cfg->lib[i]->code_prefix,instream);
get_int(c,instream);
cfg->lib[i]->sort = c;
for(j=0;j<3;j++)
get_int(cfg->lib[i]->misc, instream);
for(j=0;j<1;j++)
get_int(n,instream); /* 0x0000 */
for(j=0;j<16;j++)
......@@ -338,6 +341,8 @@ BOOL read_file_cfg(scfg_t* cfg, char* error)
return allocerr(instream,error,offset,fname,sizeof(dir_t));
memset(cfg->dir[i],0,sizeof(dir_t));
cfg->dir[i]->dirnum = i;
get_int(cfg->dir[i]->lib,instream);
get_str(cfg->dir[i]->lname,instream);
get_str(cfg->dir[i]->sname,instream);
......
......@@ -477,7 +477,7 @@ BOOL DLLCALL write_msgs_cfg(scfg_t* cfg, int backup_level)
put_str(cfg->grp[i]->sname,stream);
put_str(cfg->grp[i]->arstr,stream);
put_str(cfg->grp[i]->code_prefix,stream);
c=0;
c=cfg->grp[i]->sort;
put_int(c,stream);
n=0;
for(j=0;j<27;j++)
......@@ -498,97 +498,101 @@ BOOL DLLCALL write_msgs_cfg(scfg_t* cfg, int backup_level)
if(cfg->sub[i]->grp < cfg->total_grps) /* total VALID sub-boards */
n++;
put_int(n,stream);
for(i=0;i<cfg->total_subs;i++) {
if(cfg->sub[i]->grp >= cfg->total_grps) /* skip bogus group numbers */
continue;
put_int(cfg->sub[i]->grp,stream);
put_str(cfg->sub[i]->lname,stream);
put_str(cfg->sub[i]->sname,stream);
put_str(cfg->sub[i]->qwkname,stream);
put_str(cfg->sub[i]->code_suffix,stream);
#if 1
if(cfg->sub[i]->data_dir[0]) {
backslash(cfg->sub[i]->data_dir);
md(cfg->sub[i]->data_dir);
}
#endif
put_str(cfg->sub[i]->data_dir,stream);
put_str(cfg->sub[i]->arstr,stream);
put_str(cfg->sub[i]->read_arstr,stream);
put_str(cfg->sub[i]->post_arstr,stream);
put_str(cfg->sub[i]->op_arstr,stream);
l=(cfg->sub[i]->misc&(~SUB_HDRMOD)); /* Don't write mod bit */
put_int(l,stream);
put_str(cfg->sub[i]->tagline,stream);
put_str(cfg->sub[i]->origline,stream);
put_str(cfg->sub[i]->post_sem,stream);
put_str(cfg->sub[i]->newsgroup,stream);
put_int(cfg->sub[i]->faddr,stream);
put_int(cfg->sub[i]->maxmsgs,stream);
put_int(cfg->sub[i]->maxcrcs,stream);
put_int(cfg->sub[i]->maxage,stream);
put_int(cfg->sub[i]->ptridx,stream);
put_str(cfg->sub[i]->mod_arstr,stream);
put_int(cfg->sub[i]->qwkconf,stream);
c=0;
put_int(c,stream);
n=0;
for(k=0;k<26;k++)
put_int(n,stream);
if(all_msghdr || (cfg->sub[i]->misc&SUB_HDRMOD && !no_msghdr)) {
if(!cfg->sub[i]->data_dir[0])
SAFEPRINTF(smb.file,"%ssubs",cfg->data_dir);
else
SAFECOPY(smb.file,cfg->sub[i]->data_dir);
prep_dir(cfg->ctrl_dir,smb.file,sizeof(smb.file));
SAFEPRINTF2(str,"%s%s"
,cfg->grp[cfg->sub[i]->grp]->code_prefix
,cfg->sub[i]->code_suffix);
strlwr(str);
strcat(smb.file,str);
if(smb_open(&smb)!=0) {
/* errormsg(WHERE,ERR_OPEN,smb.file,x); */
continue;
unsigned int subnum = 0; /* New sub-board numbering (as saved) */
for(unsigned grp = 0; grp < cfg->total_grps; grp++) {
for(i=0;i<cfg->total_subs;i++) {
if(cfg->sub[i]->grp != grp)
continue;
cfg->sub[i]->subnum = subnum++;
put_int(cfg->sub[i]->grp,stream);
put_str(cfg->sub[i]->lname,stream);
put_str(cfg->sub[i]->sname,stream);
put_str(cfg->sub[i]->qwkname,stream);
put_str(cfg->sub[i]->code_suffix,stream);
#if 1
if(cfg->sub[i]->data_dir[0]) {
backslash(cfg->sub[i]->data_dir);
md(cfg->sub[i]->data_dir);
}
if(!filelength(fileno(smb.shd_fp))) {
smb.status.max_crcs=cfg->sub[i]->maxcrcs;
#endif
put_str(cfg->sub[i]->data_dir,stream);
put_str(cfg->sub[i]->arstr,stream);
put_str(cfg->sub[i]->read_arstr,stream);
put_str(cfg->sub[i]->post_arstr,stream);
put_str(cfg->sub[i]->op_arstr,stream);
l=(cfg->sub[i]->misc&(~SUB_HDRMOD)); /* Don't write mod bit */
put_int(l,stream);
put_str(cfg->sub[i]->tagline,stream);
put_str(cfg->sub[i]->origline,stream);
put_str(cfg->sub[i]->post_sem,stream);
put_str(cfg->sub[i]->newsgroup,stream);
put_int(cfg->sub[i]->faddr,stream);
put_int(cfg->sub[i]->maxmsgs,stream);
put_int(cfg->sub[i]->maxcrcs,stream);
put_int(cfg->sub[i]->maxage,stream);
put_int(cfg->sub[i]->ptridx,stream);
put_str(cfg->sub[i]->mod_arstr,stream);
put_int(cfg->sub[i]->qwkconf,stream);
c=0;
put_int(c,stream);
n=0;
for(k=0;k<26;k++)
put_int(n,stream);
if(all_msghdr || (cfg->sub[i]->misc&SUB_HDRMOD && !no_msghdr)) {
if(!cfg->sub[i]->data_dir[0])
SAFEPRINTF(smb.file,"%ssubs",cfg->data_dir);
else
SAFECOPY(smb.file,cfg->sub[i]->data_dir);
prep_dir(cfg->ctrl_dir,smb.file,sizeof(smb.file));
SAFEPRINTF2(str,"%s%s"
,cfg->grp[cfg->sub[i]->grp]->code_prefix
,cfg->sub[i]->code_suffix);
strlwr(str);
strcat(smb.file,str);
if(smb_open(&smb)!=0) {
/* errormsg(WHERE,ERR_OPEN,smb.file,x); */
continue;
}
if(!filelength(fileno(smb.shd_fp))) {
smb.status.max_crcs=cfg->sub[i]->maxcrcs;
smb.status.max_msgs=cfg->sub[i]->maxmsgs;
smb.status.max_age=cfg->sub[i]->maxage;
smb.status.attr=cfg->sub[i]->misc&SUB_HYPER ? SMB_HYPERALLOC :0;
if(smb_create(&smb)!=0)
/* errormsg(WHERE,ERR_CREATE,smb.file,x) */;
smb_close(&smb);
continue;
}
if(smb_locksmbhdr(&smb)!=0) {
smb_close(&smb);
/* errormsg(WHERE,ERR_LOCK,smb.file,x) */;
continue;
}
if(smb_getstatus(&smb)!=0) {
smb_close(&smb);
/* errormsg(WHERE,ERR_READ,smb.file,x) */;
continue;
}
if((!(cfg->sub[i]->misc&SUB_HYPER) || smb.status.attr&SMB_HYPERALLOC)
&& smb.status.max_msgs==cfg->sub[i]->maxmsgs
&& smb.status.max_crcs==cfg->sub[i]->maxcrcs
&& smb.status.max_age==cfg->sub[i]->maxage) { /* No change */
smb_close(&smb);
continue;
}
smb.status.max_msgs=cfg->sub[i]->maxmsgs;
smb.status.max_crcs=cfg->sub[i]->maxcrcs;
smb.status.max_age=cfg->sub[i]->maxage;
smb.status.attr=cfg->sub[i]->misc&SUB_HYPER ? SMB_HYPERALLOC :0;