/* Partially preprocesses the current line of input. If the input * contains a preprocessor statement, the state of ppproc is updated * to reflect the current section, and if necessary the line of input * will be altered for output. */ static void seq(struct ppproc *ppp) { char const *input; char const *cmd; enum status status; int incomment; enum ppcmd id; int size, n; incomment = ccommentp(ppp->cl); ppp->absorb = FALSE; input = examinechar(ppp->cl, ppp->line); while (!preproclinep(ppp->cl)) { if (endoflinep(ppp->cl)) return; input = nextchar(ppp->cl, input); } cmd = skipwhite(ppp->cl, nextchar(ppp->cl, input)); input = getpreprocessorcmd(ppp->cl, cmd, &id); switch (id) { case cmdIfdef: case cmdIfndef: if (ppp->level + 1 >= sizearray(ppp->stack)) { error(errIfsTooDeep); break; } ++ppp->level; ppp->stack[ppp->level] = F_If | F_Ifdef; if (!ppp->copy) { input = restofline(ppp->cl, input); break; } ppp->stack[ppp->level] |= F_Copy; size = getidentifierlength(input); if (!size) { error(errEmptyIf); break; } if (findsymbolinset(ppp->defs, input, NULL)) n = statDefined; else if (findsymbolinset(ppp->undefs, input, NULL)) n = statUndefined; else n = statUnaffected; input = skipwhite(ppp->cl, nextchars(ppp->cl, input, size)); if (!endoflinep(ppp->cl)) { error(errSyntax); break; } if (n != statUnaffected) { ppp->absorb = TRUE; ppp->stack[ppp->level] |= F_Ours; ppp->copy = n == (id == cmdIfdef ? statDefined : statUndefined); } break; case cmdIf: if (ppp->level + 1 >= sizearray(ppp->stack)) { error(errIfsTooDeep); break; } ++ppp->level; ppp->stack[ppp->level] = F_If | (ppp->copy ? F_Copy : 0); if (!ppp->copy) { input = restofline(ppp->cl, input); break; } input = seqif(ppp, (char*)input, &status); if (status == statError) break; input = skipwhite(ppp->cl, input); if (!endoflinep(ppp->cl)) { error(errIfSyntax); break; } if (status == statDefined || status == statUndefined) { ppp->absorb = TRUE; ppp->stack[ppp->level] |= F_Ours; ppp->copy = status == statDefined; } break; case cmdElse: if (ppp->level < 0 || (ppp->stack[ppp->level] & F_Else)) { error(errDanglingElse); break; } ppp->stack[ppp->level] |= F_Else; if (!endoflinep(ppp->cl)) { error(errSyntax); break; } if (ppp->stack[ppp->level] & F_Ours) { ppp->copy = !ppp->copy; ppp->absorb = TRUE; n = ppp->level; while (ppp->stack[n] & F_Elif) { if (ppp->stack[n] & F_ElseModify) { ppp->absorb = TRUE; break; } --n; if (!(ppp->stack[n] & F_Ours)) ppp->absorb = FALSE; } } break; case cmdElif: if (ppp->level < 0 || !(ppp->stack[ppp->level] & F_If) || (ppp->stack[ppp->level] & F_Else)) { error(errDanglingElse); break; } else if (ppp->level + 1 >= sizearray(ppp->stack)) { error(errIfsTooDeep); break; } if (ppp->stack[ppp->level] & F_Ifdef) error(errElifWithIfdef); ppp->stack[ppp->level] |= F_Else; if (ppp->stack[ppp->level] & F_Ours) ppp->copy = !ppp->copy; ++ppp->level; ppp->stack[ppp->level] = F_If | F_Elif | (ppp->copy ? F_Copy : 0); if (!ppp->copy) { input = restofline(ppp->cl, input); break; } input = seqif(ppp, (char*)input, &status); if (status == statError) break; input = skipwhite(ppp->cl, input); if (!endoflinep(ppp->cl)) { error(errIfSyntax); break; } if (status == statUndefined) { ppp->copy = FALSE; ppp->absorb = TRUE; ppp->stack[ppp->level] |= F_Ours; } else if (status == statDefined) { ppp->absorb = TRUE; n = ppp->level; while (ppp->stack[n] & F_Elif) { --n; if (!(ppp->stack[n] & F_Ours)) { strcpy((char*)cmd, "else"); ppp->stack[ppp->level] |= F_ElseModify; ppp->absorb = FALSE; break; } } ppp->stack[ppp->level] |= F_Ours; } else { n = ppp->level; while (ppp->stack[n] & F_Elif) { --n; if (!(ppp->stack[n] & F_Ours)) { n = -1; break; } } if (n >= 0) { memmove((char*)cmd, cmd + 2, strlen(cmd + 2) + 1); ppp->stack[ppp->level] |= F_IfModify; } } break; case cmdEndif: if (ppp->level < 0) { error(errDanglingEnd); break; } if (!endoflinep(ppp->cl)) { error(errSyntax); input = restofline(ppp->cl, input); } ppp->absorb = TRUE; for ( ; ppp->stack[ppp->level] & F_Elif ; --ppp->level) { if (ppp->stack[ppp->level] & (F_IfModify | F_ElseModify)) ppp->absorb = FALSE; } if (ppp->absorb) ppp->absorb = ppp->stack[ppp->level] & F_Ours; ppp->copy = ppp->stack[ppp->level] & F_Copy; --ppp->level; break; default: input = restofline(ppp->cl, input); break; } if (ppp->absorb && incomment != ccommentp(ppp->cl)) error(errBrokenComment); }
int readcontrolfile(struct letter *let, char *qid) { int fd; char ctrlfile[sizeof(CTRLPFX)+6+1]; char *ctrl = 0; size_t size; char *sep; char *p, *q, *end; struct address to; sprintf(ctrlfile, CTRLPFX "%.6s", qid); if ( (fd = open(ctrlfile, O_RDONLY)) != -1) { ctrl = mapfd(fd, &size); close(fd); } if (ctrl == 0) return 0; reset(let); strlcpy(let->qid, qid, sizeof let->qid); p = ctrl; end = p + size; for (p = ctrl ; (p < end) && (q = memchr(p, '\n', end-p)); p = q+1) { switch (*p) { case C_FROM: /* From: address */ if (let->from) freeaddress(let->from); if ( (let->from = calloc(1, sizeof let->from[0])) == 0 ) { syslog(LOG_ERR, "out of memory"); abort(); } if ( (let->from->full = restofline(1+p, q)) == 0) { syslog(LOG_ERR, "out of memory"); abort(); } let->from->domain = strdup(let->env->localhost); break; case C_TO: /* To: address */ memset(&to, 0, sizeof to); if ( (to.full = restofline(1+p, q)) == 0) { syslog(LOG_ERR, "out of memory"); abort(); } if ( ((sep = strchr(to.full, '|')) == 0) || (sep == to.full) ) { syslog(LOG_ERR, "Qid %s: corrupted to address <%s>", let->qid, to.full); abort(); } *sep++ = 0; to.domain = sep; if ( *to.domain == 0 ) { syslog(LOG_ERR, "Qid %s: corrupted to address <%s>", let->qid, to.full); abort(); } else if (newrecipient(&let->remote, &to, emUSER, NOBODY_UID, NOBODY_GID) == -1) abort(); free(to.full); break; case C_FLAGS: /* extra flags */ switch (p[1]) { case 'H': let->has_headers = 1; break; case 'F': let->mesgfrom = 1; break; } break; case C_HEADER: /* real headers live past here */ if (1+q < end) { let->headtext = restofline(1+q, end); let->headsize = strlen(let->headtext); } else { let->headtext = calloc(1,1); let->headsize = 0; } munmap(ctrl,size); return 1; } } munmap(ctrl, size); return 0; }