+ dcreate(""); /* This is all we do, the rest is up to ezmlmrc */
+ /* do it after opening template to avoid aborts */
+ /* with created DIR. Well we also write DIR/key */
+ /* at the end except in -e[dit] mode. */
+
+ substdio_fdbuf(&sstext,read,fdin,textbuf,sizeof(textbuf));
+ if (!stralloc_0(&oldfname)) die_nomem(); /* init oldfname */
+ flagdo = 0;
+
+ if (getln(&sstext,&line,&match,'\n') == -1)
+ strerr_die4sys(111,FATAL,ERR_READ,template.s,": ");
+ if (!match)
+ strerr_die4sys(111,FATAL,ERR_READ,template.s,": ");
+ i = str_rchr(EZIDX_VERSION,'-'); /* check version */
+ if (EZIDX_VERSION[i]) i++;
+ j = 0;
+ while (line.s[j] == EZIDX_VERSION[i] && j < line.len &&
+ EZIDX_VERSION[i] != '.' && EZIDX_VERSION[i]) {
+ i++; j++; /* major */
+ } /* first minor */
+ if (EZIDX_VERSION[i] != '.' || j + 1 >= line.len ||
+ EZIDX_VERSION[i+1] != line.s[j+1])
+ strerr_warn2(WARNING,ERR_VERSION, (struct strerr *) 0);
+
+ for (;;) {
+ if (getln(&sstext,&line,&match,'\n') == -1)
+ strerr_die4sys(111,FATAL,ERR_READ,template.s,": ");
+ if (!match)
+ break;
+ if (line.s[0] == '#') /* comment */
+ continue;
+ if (!stralloc_0(&line)) die_nomem();
+ if (line.s[0] == '<' && line.s[1] == '/') { /* tag */
+ if (line.s[str_chr(line.s,'.')])
+ strerr_die3x(100,FATAL,ERR_PERIOD,line.s);
+ flagdo = 1;
+ flagover = 0;
+ hashpos = 0;
+ pos = str_chr(line.s+2,'#')+2;
+ if (line.s[pos]) {
+ hashpos = pos;
+ pos++;
+ flagnot = 0;
+ while ((ch = line.s[pos]) &&
+ (line.s[pos] != '/' && line.s[pos+1] != '>')) {
+ if (ch == '^') {
+ flagnot = 1;
+ pos++;
+ continue;
+ }
+ /* E is ignored. For files => create unless exists */
+ if (ch == 'E' && !flagnot || ch == 'e' && flagnot) {
+ if (flags['e' - 'a'] && !flagforce)
+ flagover = 1; /* ignore #E & #^e, but set flagover */
+ } else if (ch >= 'a' && ch <= 'z')
+ flagdo &= (flags[ch - 'a'] ^ flagnot);
+ else if (ch >= 'A' && ch <= 'Z')
+ flagdo &= !(flags[ch - 'A'] ^ flagnot);
+ else if (ch >= '0' && ch <= '9')
+ flagdo &= (popt[ch - '0'] && *popt[ch - '0']) ^flagnot;
+ flagnot = 0;
+ pos++;
+ }
+ if (line.s[pos] != '/' || line.s[pos+1] != '>')
+ strerr_die3x(100,FATAL,ERR_ENDTAG,line.s);
+ } else {
+ flagdo = 1;
+ pos = 2; /* name needs to be >= 1 char */
+ while (line.s[pos = str_chr(line.s+pos,'/')+pos]) {
+ if (line.s[pos+1] == '>')
+ break;
+ pos++;
+ }
+ if (!line.s[pos])
+ strerr_die3x(100,FATAL,ERR_ENDTAG,line.s);
+ }
+ if (hashpos)
+ pos = hashpos; /* points to after file name */
+
+ if (line.s[2] == '+') { /* mkdir */
+ if (!flagdo)
+ continue;
+ if (!stralloc_copys(&dname,"/")) die_nomem();
+ if (!stralloc_catb(&dname,line.s+3,pos-3)) die_nomem();
+ if (!stralloc_0(&dname)) die_nomem();
+ dcreate(dname.s);
+ flagdo = 0;
+ continue;
+ } else if (line.s[2] == ':') { /* ln -s */
+ if (!flagdo)
+ continue;
+ slpos = str_chr(line.s + 3,'/') + 3;
+ if (slpos >= pos)
+ strerr_die3x(100,FATAL,ERR_LINKDIR,line.s);
+ if (!stralloc_copyb(&dname,line.s+slpos,pos-slpos)) die_nomem();
+ if (!stralloc_copyb(&lname,line.s+3,slpos-3)) die_nomem();
+ if (!stralloc_0(&dname)) die_nomem();
+ if (!stralloc_0(&lname)) die_nomem();
+ linkdotdir(lname.s,dname.s);
+ flagdo = 0;
+ continue;
+ } else if (line.s[2] == '-') { /* rm */
+ if (!flagdo)
+ continue;
+ if (!stralloc_copys(&dname,"/")) die_nomem();
+ if (!stralloc_catb(&dname,line.s+3,pos-3)) die_nomem();
+ if (!stralloc_0(&dname)) die_nomem();
+ frm(dname.s);
+ flagdo = 0;
+ continue;
+ }
+ /* only plain files left */
+ /* first get file name */
+ if (pos > 2) { /* </#ai/> => add to open file */
+ if (!stralloc_copyb(&fname,line.s+1,pos-1)) die_nomem();
+ if (!stralloc_0(&fname)) die_nomem();
+ }
+
+ if (str_diff(fname.s, oldfname.s)) {
+ flagnotexist = 1;
+ /* Treat special case of #E when editing which _should*/
+ /* write only if the file does not exist. flagover */
+ /* is set if we need to check */
+ if (flagover) { /* skip if exists */
+ dirplusmake(fname.s); /* decided by FIRST tag for file */
+ fdtmp = open_read(dirplus.s);
+ if (fdtmp == -1) {
+ if (errno != error_noent)
+ strerr_die3sys(111,ERR_OPEN,dirplus.s,": ");
+ } else {
+ flagnotexist = 0; /* already there - don't do it */
+ close(fdtmp);
+ }
+ }
+ if (oldfname.len > 1) {
+ f_close();
+ if (!stralloc_copys(&oldfname,"")) die_nomem();
+ if (!stralloc_0(&oldfname)) die_nomem();
+ }
+ if (flagdo && flagnotexist) {
+ if (!fname.len)
+ strerr_die3x(100,FATAL,ERR_FILENAME,line.s);
+ f_open(fname.s);
+ if (!stralloc_copy(&oldfname,&fname)) die_nomem();
+ }
+ }
+ if (flagdo) flagdo = flagnotexist;
+ continue;
+ } else if (!flagdo)
+ continue; /* part not to go out */
+ last = -1;
+ next = 0;
+ outline.len = 0;
+ for (;;) {
+ pos = next + str_chr(line.s+next,'<');
+ if (line.s[pos] &&
+ line.s[pos+1] == '#' &&
+ line.s[pos+2] &&
+ line.s[pos+3] == '#' &&
+ line.s[pos+4] == '>') { /* host/local */
+ if (!stralloc_catb(&outline,line.s+last+1,pos-last-1))
+ die_nomem();
+ switch (line.s[pos+2]) {
+ case 'B': /* path to ezmlm binaries (no trailing /) */
+ if (!stralloc_cats(&outline,auto_bin)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ case 'C': /* digestcode */
+ if (code && *code)
+ if (!stralloc_cats(&outline,code)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ case 'D': /* listdir */
+ if (!stralloc_cats(&outline,dir)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ case 'F': /* flags */
+ if (!stralloc_cat(&outline,&f)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ case 'H': /* hostname */
+ if (!stralloc_cats(&outline,host)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ case 'L': /* local */
+ if (!stralloc_cats(&outline,local)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ case 'T': /* dot */
+ if (!stralloc_cats(&outline,dot)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ case 'X': /* config file name */
+ if (cfname)
+ if (!stralloc_cats(&outline,cfname)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ default: /* copy unknown tag as is for e.g. <#A#> and*/
+ /* <#R#> to be processed by -manage/store */
+ /* stuff in args for <#0#> .. <#9#> */
+ if ((line.s[pos+2] >= '0') && (line.s[pos+2] <= '9')) {
+ if (popt[line.s[pos+2] - '0'])
+ if (!stralloc_cats(&outline,popt[line.s[pos+2]-'0']))
+ die_nomem();
+ } else
+ if (!stralloc_catb(&outline,line.s+pos,5)) die_nomem();
+ last = pos + 4; next = pos + 5; break;
+ }
+ } else { /* not tag */
+ if (line.s[pos]) {
+ next++;
+ } else {
+ if (!stralloc_catb(&outline,line.s+last+1,line.len-last-1))
+ die_nomem();
+ f_puts(outline.s);
+ break;
+ }
+ }
+ }
+ }
+
+ close(fdin);
+ if (oldfname.len > 1)
+ f_close();
+
+ if (!flags['e' - 'a']) { /* don't redo key when editing a list */
+ f_open("/key");
+ f_put(key.s,key.len);
+ f_close();
+ }