/* * vSplitBlockList - split the block list in the various parts * * Split the blocklist in a Text block list, a Footnote block list, a * HeaderFooter block list, a Macro block list, an Annotation block list, * an Endnote block list, a TextBox list and a HeaderTextBox list. * * NOTE: * The various ul*Len input parameters are given in characters, but the * length of the blocks are in bytes. */ void vSplitBlockList(FILE *pFile, ULONG ulTextLen, ULONG ulFootnoteLen, ULONG ulHdrFtrLen, ULONG ulMacroLen, ULONG ulAnnotationLen, ULONG ulEndnoteLen, ULONG ulTextBoxLen, ULONG ulHdrTextBoxLen, BOOL bMustExtend) { list_mem_type *apAnchors[8]; list_mem_type *pGarbageAnchor, *pCurr; size_t tIndex; DBG_MSG("vSplitBlockList"); pGarbageAnchor = NULL; DBG_MSG_C(ulTextLen != 0, "Text block list"); vSpitList(&pTextAnchor, &pFootnoteAnchor, ulTextLen); DBG_MSG_C(ulFootnoteLen != 0, "Footnote block list"); vSpitList(&pFootnoteAnchor, &pHdrFtrAnchor, ulFootnoteLen); DBG_MSG_C(ulHdrFtrLen != 0, "Header/Footer block list"); vSpitList(&pHdrFtrAnchor, &pMacroAnchor, ulHdrFtrLen); DBG_MSG_C(ulMacroLen != 0, "Macro block list"); vSpitList(&pMacroAnchor, &pAnnotationAnchor, ulMacroLen); DBG_MSG_C(ulAnnotationLen != 0, "Annotation block list"); vSpitList(&pAnnotationAnchor, &pEndnoteAnchor, ulAnnotationLen); DBG_MSG_C(ulEndnoteLen != 0, "Endnote block list"); vSpitList(&pEndnoteAnchor, &pTextBoxAnchor, ulEndnoteLen); DBG_MSG_C(ulTextBoxLen != 0, "Textbox block list"); vSpitList(&pTextBoxAnchor, &pHdrTextBoxAnchor, ulTextBoxLen); DBG_MSG_C(ulHdrTextBoxLen != 0, "HeaderTextbox block list"); vSpitList(&pHdrTextBoxAnchor, &pGarbageAnchor, ulHdrTextBoxLen); /* Free the garbage block list, this should not be needed */ DBG_DEC_C(pGarbageAnchor != NULL, pGarbageAnchor->tInfo.ulLength); pGarbageAnchor = pFreeOneList(pGarbageAnchor); #if defined(DEBUG) vCheckList(pTextAnchor, ulTextLen, "Software error (Text)"); vCheckList(pFootnoteAnchor, ulFootnoteLen, "Software error (Footnote)"); vCheckList(pHdrFtrAnchor, ulHdrFtrLen, "Software error (Hdr/Ftr)"); vCheckList(pMacroAnchor, ulMacroLen, "Software error (Macro)"); vCheckList(pAnnotationAnchor, ulAnnotationLen, "Software error (Annotation)"); vCheckList(pEndnoteAnchor, ulEndnoteLen, "Software error (Endnote)"); vCheckList(pTextBoxAnchor, ulTextBoxLen, "Software error (TextBox)"); vCheckList(pHdrTextBoxAnchor, ulHdrTextBoxLen, "Software error (HdrTextBox)"); #endif /* DEBUG */ /* Remove the list if the text box is empty */ if (bIsEmptyBox(pFile, pTextBoxAnchor)) { pTextBoxAnchor = pFreeOneList(pTextBoxAnchor); } if (bIsEmptyBox(pFile, pHdrTextBoxAnchor)) { pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor); } if (!bMustExtend) { return; } /* * All blocks (except the last one) must have a length that * is a multiple of the Big Block Size */ apAnchors[0] = pTextAnchor; apAnchors[1] = pFootnoteAnchor; apAnchors[2] = pHdrFtrAnchor; apAnchors[3] = pMacroAnchor; apAnchors[4] = pAnnotationAnchor; apAnchors[5] = pEndnoteAnchor; apAnchors[6] = pTextBoxAnchor; apAnchors[7] = pHdrTextBoxAnchor; for (tIndex = 0; tIndex < elementsof(apAnchors); tIndex++) { for (pCurr = apAnchors[tIndex]; pCurr != NULL; pCurr = pCurr->pNext) { if (pCurr->pNext != NULL && pCurr->tInfo.ulLength % BIG_BLOCK_SIZE != 0) { DBG_DEC(tIndex); DBG_HEX(pCurr->tInfo.ulFileOffset); DBG_HEX(pCurr->tInfo.ulCharPos); DBG_DEC(pCurr->tInfo.ulLength); pCurr->tInfo.ulLength /= BIG_BLOCK_SIZE; pCurr->tInfo.ulLength++; pCurr->tInfo.ulLength *= BIG_BLOCK_SIZE; DBG_DEC(pCurr->tInfo.ulLength); } } } } /* end of vSplitBlockList */
char* fmtre(const char* as) { register char* s = (char*)as; register int c; register char* t; register Stack_t* p; char* x; int n; int end; char* buf; Stack_t stack[32]; end = 1; c = 2 * strlen(s) + 1; t = buf = fmtbuf(c); p = stack; if (*s != '*' || *(s + 1) == '(' || *(s + 1) == '-' && *(s + 2) == '(') *t++ = '^'; else s++; for (;;) { switch (c = *s++) { case 0: break; case '\\': if (!(c = *s++) || c == '{' || c == '}') return 0; *t++ = '\\'; if ((*t++ = c) == '(' && *s == '|') { *t++ = *s++; goto logical; } continue; case '[': *t++ = c; n = 0; if ((c = *s++) == '!') { *t++ = '^'; c = *s++; } else if (c == '^') { if ((c = *s++) == ']') { *(t - 1) = '\\'; *t++ = '^'; continue; } n = '^'; } for (;;) { if (!(*t++ = c)) return 0; if ((c = *s++) == ']') { if (n) *t++ = n; *t++ = c; break; } } continue; case '{': for (x = s; *x && *x != '}'; x++); if (*x++ && (*x == '(' || *x == '-' && *(x + 1) == '(')) { if (p >= &stack[elementsof(stack)]) return 0; p->beg = s - 1; s = x; p->len = s - p->beg; if (p->min = *s == '-') s++; p++; *t++ = *s++; } else *t++ = c; continue; case '*': if (!*s) { end = 0; break; } /*FALLTHROUGH*/ case '?': case '+': case '@': case '!': case '~': if (*s == '(' || c != '~' && *s == '-' && *(s + 1) == '(') { if (p >= &stack[elementsof(stack)]) return 0; p->beg = s - 1; if (c == '~') { if (*(s + 1) == 'E' && *(s + 2) == ')') { for (s += 3; *t = *s; t++, s++); continue; } p->len = 0; p->min = 0; *t++ = *s++; *t++ = '?'; } else { p->len = c != '@'; if (p->min = *s == '-') s++; *t++ = *s++; } p++; } else { switch (c) { case '*': *t++ = '.'; break; case '?': c = '.'; break; case '+': case '!': *t++ = '\\'; break; } *t++ = c; } continue; case '(': if (p >= &stack[elementsof(stack)]) return 0; p->beg = s - 1; p->len = 0; p->min = 0; p++; *t++ = c; continue; case ')': if (p == stack) return 0; *t++ = c; p--; for (c = 0; c < p->len; c++) *t++ = p->beg[c]; if (p->min) *t++ = '?'; continue; case '^': case '.': case '$': *t++ = '\\'; *t++ = c; continue; case '|': if (t == buf || *(t - 1) == '(') return 0; logical: if (!*s || *s == ')') return 0; /*FALLTHROUGH*/ default: *t++ = c; continue; } break; } if (p != stack) return 0; if (end) *t++ = '$'; *t = 0; return buf; }
int ftwalk(const char* path, int (*userf)(Ftw_t*), int flags, int (*comparf)(Ftw_t*, Ftw_t*)) { register FTS* f; register FTSENT* e; register int children; register int rv; int oi; int ns; int os; int nd; FTSENT* x; FTSENT* dd[2]; flags ^= FTS_ONEPATH; if (flags & FTW_TWICE) flags &= ~(FTS_NOPREORDER|FTS_NOPOSTORDER); else if (flags & FTW_POST) flags |= FTS_NOPREORDER; else flags |= FTS_NOPOSTORDER; if (children = flags & FTW_CHILDREN) flags |= FTS_SEEDOT; state.comparf = comparf; if (!(f = fts_open((char* const*)path, flags, comparf ? ftscompare : 0))) { if (!path || !(flags & FTS_ONEPATH) && !(path = (const char*)(*((char**)path)))) return -1; ns = strlen(path) + 1; if (!(e = newof(0, FTSENT, 1, ns))) return -1; e->fts_accpath = e->fts_name = e->fts_path = strcpy((char*)(e + 1), path); e->fts_namelen = e->fts_pathlen = ns; e->fts_info = FTS_NS; e->parent = e; e->parent->link = e; rv = (*userf)((Ftw_t*)e); free(e); return rv; } rv = 0; if (children && (e = fts_children(f, 0))) { nd = 0; for (x = e; x; x = x->link) if (x->info & FTS_DD) { x->statb = *x->fts_statp; x->info &= ~FTS_DD; dd[nd++] = x; if (nd >= elementsof(dd)) break; } e->parent->link = e; rv = (*userf)((Ftw_t*)e->parent); e->parent->link = 0; while (nd > 0) dd[--nd]->info |= FTS_DD; for (x = e; x; x = x->link) if (!(x->info & FTS_D)) x->status = FTS_SKIP; } while (!rv && (e = fts_read(f))) { oi = e->info; os = e->status; ns = e->status = e->path == e->fts_accpath ? FTW_PATH : FTW_NAME; nd = 0; switch (e->info) { case FTS_D: case FTS_DNX: if (children) for (x = fts_children(f, 0); x; x = x->link) if (x->info & FTS_DD) { x->statb = *x->fts_statp; x->info &= ~FTS_DD; dd[nd++] = x; if (nd >= elementsof(dd)) break; } break; case FTS_DOT: continue; case FTS_ERR: case FTS_SLNONE: e->info = FTS_NS; break; case FTS_NSOK: e->info = FTS_NSOK; break; } rv = (*userf)((Ftw_t*)e); e->info = oi; if (e->status == ns) e->status = os; while (nd > 0) dd[--nd]->info |= FTS_DD; } fts_close(f); return rv; }
static Extype_t eval(Expr_t* ex, register Exnode_t* expr, void* env) { register Exnode_t* x; register Exnode_t* a; register Extype_t** t; register int n; Extype_t v; Extype_t r; Extype_t i; char* e; Exnode_t tmp; Exassoc_t* assoc; Extype_t args[FRAME+1]; Extype_t save[FRAME]; if (!expr || ex->loopcount) { v.integer = 1; return v; } x = expr->data.operand.left; switch (expr->op) { case BREAK: case CONTINUE: v = eval(ex, x, env); ex->loopcount = v.integer; ex->loopop = expr->op; return v; case CONSTANT: return expr->data.constant.value; case DEC: n = -1; add: if (x->op == DYNAMIC) r = getdyn(ex, x, env, &assoc); else { if (x->data.variable.index) i = eval(ex, x->data.variable.index, env); else i.integer = EX_SCALAR; r = (*ex->disc->getf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)i.integer, ex->disc); } v = r; switch (x->type) { case FLOATING: v.floating += n; break; case INTEGER: case UNSIGNED: v.integer += n; break; default: goto huh; } set: if (x->op == DYNAMIC) { if (x->type == STRING) { v.string = vmstrdup(ex->vm, v.string); if (e = assoc ? assoc->value.string : x->data.variable.symbol->value->data.constant.value.string) vmfree(ex->vm, e); } if (assoc) assoc->value = v; else x->data.variable.symbol->value->data.constant.value = v; } else { if (x->data.variable.index) i = eval(ex, x->data.variable.index, env); else i.integer = EX_SCALAR; if ((*ex->disc->setf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)i.integer, v, ex->disc) < 0) exerror("%s: cannot set value", x->data.variable.symbol->name); } if (expr->subop == PRE) r = v; return r; case DYNAMIC: return getdyn(ex, expr, env, &assoc); case EXIT: v = eval(ex, x, env); exit((int)v.integer); /*NOTREACHED*/ v.integer = -1; return v; case IF: v = eval(ex, x, env); if (v.integer) eval(ex, expr->data.operand.right->data.operand.left, env); else eval(ex, expr->data.operand.right->data.operand.right, env); v.integer = 1; return v; case FOR: case WHILE: expr = expr->data.operand.right; for (;;) { r = eval(ex, x, env); if (!r.integer) { v.integer = 1; return v; } if (expr->data.operand.right) { eval(ex, expr->data.operand.right, env); if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) { v.integer = 0; return v; } } if (expr->data.operand.left) eval(ex, expr->data.operand.left, env); } /*NOTREACHED*/ case SWITCH: v = eval(ex, x, env); i.integer = x->type; r.integer = 0; x = expr->data.operand.right; a = x->data.select.statement; n = 0; while (x = x->data.select.next) { if (!(t = x->data.select.constant)) n = 1; else for (; *t; t++) { switch ((int)i.integer) { case INTEGER: case UNSIGNED: if ((*t)->integer == v.integer) break; continue; case STRING: if ((ex->disc->version >= 19981111L && ex->disc->matchf) ? (*ex->disc->matchf)(ex, x, (*t)->string, expr->data.operand.left, v.string, env, ex->disc) : strmatch((*t)->string, v.string)) break; continue; case FLOATING: if ((*t)->floating == v.floating) break; continue; } n = 1; break; } if (n) { if (!x->data.select.statement) { r.integer = 1; break; } r = eval(ex, x->data.select.statement, env); if (ex->loopcount > 0) { ex->loopcount--; break; } } } if (!n && a) { r = eval(ex, a, env); if (ex->loopcount > 0) ex->loopcount--; } return r; case ITERATE: v.integer = 0; if (expr->data.generate.array->op == DYNAMIC) { n = expr->data.generate.index->type == STRING; for (assoc = (Exassoc_t*)dtfirst((Dt_t*)expr->data.generate.array->data.variable.symbol->local.pointer); assoc; assoc = (Exassoc_t*)dtnext((Dt_t*)expr->data.generate.array->data.variable.symbol->local.pointer, assoc)) { v.integer++; if (n) expr->data.generate.index->value->data.constant.value.string = assoc->name; else expr->data.generate.index->value->data.constant.value.integer = strtol(assoc->name, NiL, 0); eval(ex, expr->data.generate.statement, env); if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) { v.integer = 0; break; } } } else { r = (*ex->disc->getf)(ex, expr, expr->data.generate.array->data.variable.symbol, expr->data.generate.array->data.variable.reference, env, 0, ex->disc); for (v.integer = 0; v.integer < r.integer; v.integer++) { expr->data.generate.index->value->data.constant.value.integer = v.integer; eval(ex, expr->data.generate.statement, env); if (ex->loopcount > 0 && (--ex->loopcount > 0 || ex->loopop != CONTINUE)) { v.integer = 0; break; } } } return v; case CALL: x = expr->data.call.args; for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && x; a = a->data.operand.right) { if (n < elementsof(args)) { save[n] = a->data.operand.left->data.variable.symbol->value->data.constant.value; args[n++] = eval(ex, x->data.operand.left, env); } else a->data.operand.left->data.variable.symbol->value->data.constant.value = eval(ex, x->data.operand.left, env); x = x->data.operand.right; } for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && n < elementsof(save); a = a->data.operand.right) a->data.operand.left->data.variable.symbol->value->data.constant.value = args[n++]; if (x) exerror("too many actual args"); else if (a) exerror("not enough actual args"); v = exeval(ex, expr->data.call.procedure->value->data.procedure.body, env); for (n = 0, a = expr->data.call.procedure->value->data.procedure.args; a && n < elementsof(save); a = a->data.operand.right) a->data.operand.left->data.variable.symbol->value->data.constant.value = save[n++]; return v; case FUNCTION: n = 0; args[n++].string = (char*)env; for (x = expr->data.operand.right; x && n < elementsof(args); x = x->data.operand.right) args[n++] = eval(ex, x->data.operand.left, env); return (*ex->disc->getf)(ex, expr->data.operand.left, expr->data.operand.left->data.variable.symbol, expr->data.operand.left->data.variable.reference, args+1, EX_CALL, ex->disc); case ID: if (expr->data.variable.index) i = eval(ex, expr->data.variable.index, env); else i.integer = EX_SCALAR; return (*ex->disc->getf)(ex, expr, expr->data.variable.symbol, expr->data.variable.reference, env, (int)i.integer, ex->disc); case INC: n = 1; goto add; case PRINTF: v.integer = print(ex, expr, env, NiL); return v; case QUERY: print(ex, expr, env, sfstderr); v.integer = !astquery(2, ""); return v; case RETURN: ex->loopret = eval(ex, x, env); ex->loopcount = 32767; ex->loopop = expr->op; return ex->loopret; case SCANF: case SSCANF: v.integer = scan(ex, expr, env, NiL); return v; case SPRINTF: print(ex, expr, env, ex->tmp); v.string = exstash(ex->tmp, ex->ve); return v; case '=': v = eval(ex, expr->data.operand.right, env); if (expr->subop != '=') { r = v; if (x->op == DYNAMIC) v = getdyn(ex, x, env, &assoc); else { if (x->data.variable.index) v = eval(ex, x->data.variable.index, env); else v.integer = EX_SCALAR; v = (*ex->disc->getf)(ex, x, x->data.variable.symbol, x->data.variable.reference, env, (int)v.integer, ex->disc); } switch (x->type) { case FLOATING: switch (expr->subop) { case '+': v.floating += r.floating; break; case '-': v.floating -= r.floating; break; case '*': v.floating *= r.floating; break; case '/': if (r.floating == 0.0) exerror("floating divide by 0"); else v.floating /= r.floating; break; case '%': if ((r.integer = r.floating) == 0) exerror("floating 0 modulus"); else v.floating = ((Sflong_t)v.floating) % r.integer; break; case '&': v.floating = ((Sflong_t)v.floating) & ((Sflong_t)r.floating); break; case '|': v.floating = ((Sflong_t)v.floating) | ((Sflong_t)r.floating); break; case '^': v.floating = ((Sflong_t)v.floating) ^ ((Sflong_t)r.floating); break; case LS: v.floating = ((Sflong_t)v.floating) << ((Sflong_t)r.floating); break; case RS: #if _WIN32 v.floating = (Sflong_t)(((Sfulong_t)v.floating) >> ((Sflong_t)r.floating)); #else v.floating = ((Sfulong_t)v.floating) >> ((Sflong_t)r.floating); #endif break; default: goto huh; } break; case INTEGER: case UNSIGNED: switch (expr->subop) { case '+': v.integer += r.integer; break; case '-': v.integer -= r.integer; break; case '*': v.integer *= r.integer; break; case '/': if (r.integer == 0) exerror("integer divide by 0"); else v.integer /= r.integer; break; case '%': if (r.integer == 0) exerror("integer 0 modulus"); else v.integer %= r.integer; break; case '&': v.integer &= r.integer; break; case '|': v.integer |= r.integer; break; case '^': v.integer ^= r.integer; break; case LS: v.integer <<= r.integer; break; case RS: v.integer = (Sfulong_t)v.integer >> r.integer; break; default: goto huh; } break; case STRING: switch (expr->subop) { case '+': v.string = str_add(ex, v.string, r.string); break; case '|': v.string = str_ior(ex, v.string, r.string); break; case '&': v.string = str_and(ex, v.string, r.string); break; case '^': v.string = str_xor(ex, v.string, r.string); break; case '%': v.string = str_mod(ex, v.string, r.string); break; case '*': v.string = str_mpy(ex, v.string, r.string); break; default: goto huh; } break; default: goto huh; } } else if (x->op == DYNAMIC)
int iface_get_initial_state(State *state) { int mib[6]; char *buf; struct if_msghdr *ifm; struct ifa_msghdr *ifam; char *lim; char *next; struct sockaddr *sa; size_t len; int naddrs; assert(state != NULL); assert(fd != -1); naddrs = 0; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = 0; mib[4] = NET_RT_IFLIST; mib[5] = ifindex; if (sysctl(mib, elementsof(mib), NULL, &len, NULL, 0) != 0) { daemon_log(LOG_ERR, "sysctl(NET_RT_IFLIST): %s", strerror(errno)); return (-1); } buf = malloc(len); if (buf == NULL) { daemon_log(LOG_ERR, "malloc(%d): %s", len, strerror(errno)); return (-1); } if (sysctl(mib, elementsof(mib), buf, &len, NULL, 0) != 0) { daemon_log(LOG_ERR, "sysctl(NET_RT_IFLIST): %s", strerror(errno)); free(buf); return (-1); } lim = buf + len; for (next = buf; next < lim; next += ifm->ifm_msglen) { ifm = (struct if_msghdr *)next; if (ifm->ifm_type == RTM_NEWADDR) { ifam = (struct ifa_msghdr *)next; sa = (struct sockaddr *)(ifam + 1); if (sa->sa_family != AF_INET) continue; ++naddrs; } } free(buf); *state = (naddrs > 0) ? STATE_SLEEPING : STATE_START; return (0); }
Recfmt_t recfmt(const void* buf, size_t size, off_t total) { register unsigned char* s; register unsigned char* t; register Sample_t* q; register unsigned int* h; register unsigned int i; unsigned int j; unsigned int k; unsigned int n; unsigned int m; unsigned int x; unsigned long f; unsigned long g; static unsigned char terminators[] = { '\n', 0x15, 0x25 }; /* * check for V format */ s = (unsigned char*)buf; t = s + size; while ((k = (t - s)) >= 4 && !s[2] && !s[3]) { if ((i = (s[0]<<8)|s[1]) > k) break; s += i; } if (!k || size > 2 * k) return REC_V_TYPE(4, 0, 2, 0, 1); s = (unsigned char*)buf; /* * check for terminated records */ for (i = 0; i < elementsof(terminators); i++) if ((t = (unsigned char*)memchr((void*)s, k = terminators[i], size / 2)) && (n = t - s + 1) > 1 && (total <= 0 || !(total % n))) { for (j = n - 1; j < size; j += n) if (s[j] != k) { n = 0; break; } if (n) return REC_D_TYPE(terminators[i]); } /* * check fixed length record frequencies */ if (!(q = newof(0, Sample_t, 1, 0))) return REC_N_TYPE(); x = 0; for (i = 0; i < size; i++) { h = q->hit + s[i]; m = i - *h; *h = i; if (m < elementsof(q->rep)) { if (m > x) x = m; q->rep[m]++; } } n = 0; m = 0; f = ~0; for (i = x; i > 1; i--) { if ((total <= 0 || !(total % i)) && q->rep[i] > q->rep[n]) { m++; g = 0; for (j = i; j < size - i; j += i) for (k = 0; k < i; k++) if (s[j + k] != s[j + k - i]) g++; g = (((g * 100) / i) * 100) / q->rep[i]; if (g <= f) { f = g; n = i; } } } if (m <= 1 && n <= 2 && total > 1 && total < 256) { n = 0; for (i = 0; i < size; i++) for (j = 0; j < elementsof(terminators); j++) if (s[i] == terminators[j]) n++; n = n ? 0 : total; } free(q); return n ? REC_F_TYPE(n) : REC_N_TYPE(); }
static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) { buffer *l; server_socket *srv_sock = con->srv_socket; //socket 插座、接口 /* check parent first */ if (dc->parent && dc->parent->context_ndx) { //如果父节点存在,但父节点未被判断或父节点是错误的,那么子节点也不能进行判断或子节点是错误的 /** * a nested conditional * * if the parent is not decided yet or false, we can't be true either */ if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "sb", "go parent", dc->parent->key); } switch (config_check_cond_cached(srv, con, dc->parent)) { case COND_RESULT_FALSE: return COND_RESULT_FALSE; case COND_RESULT_UNSET: return COND_RESULT_UNSET; default: break; } } if (dc->prev) { /** * a else branch * * we can only be executed, if all of our previous brothers * are false */ //存在前驱块,那么需要先判断前驱块状态 if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "sb", "go prev", dc->prev->key); } /* make sure prev is checked first */ config_check_cond_cached(srv, con, dc->prev); /* one of prev set me to FALSE */ //在判断前驱块状态时候有可能就已经设置了本快的状态(config_check_cond_cached函数调用如前驱块为真,该前驱块以下的块将全都设置为假),如果为假则直接返回。 switch (con->cond_cache[dc->context_ndx].result) { case COND_RESULT_FALSE: return con->cond_cache[dc->context_ndx].result; default: break; } } if (!con->conditional_is_valid[dc->comp]) { if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "dss", dc->comp, dc->key->ptr, con->conditional_is_valid[dc->comp] ? "yeah" : "nej"); } return COND_RESULT_UNSET; } /* pass the rules */ //开始实际的连接状态判断,Lighttpd1.4.20提供的条件配置有10个,分别为server_socket HTTP_URL HTTP_HOST HTTP_REFERER HTTP_USER_AGENT HTTP_COOKIE //HTTP_REMOTE_IP HTTP_QUERY_STRING HTTP_SCHEME HTTP_REQUEST_METHOD switch (dc->comp) { case COMP_HTTP_HOST: { char *ck_colon = NULL, *val_colon = NULL; if (!buffer_is_empty(con->uri.authority)) { //authority内保存是请求连接的Host信息(可能是域名也可能是IP地址) /* * append server-port to the HTTP_POST if necessary */ l = con->uri.authority; switch(dc->cond) { case CONFIG_COND_NE: case CONFIG_COND_EQ: ck_colon = strchr(dc->string->ptr, ':'); val_colon = strchr(l->ptr, ':'); if (ck_colon == val_colon) { //请求连接的Host信息与条件配置块的Host条件设置格式一致(即两者都包含有端口号或都没有包含端口号),则什么都不做。 /* nothing to do with it */ break; } if (ck_colon) { //请求连接的Host信息没有半酣端口号而条件配置块的Host包含端口号,因此给请求连接的Host加上端口号 /* condition "host:port" but client send "host" */ buffer_copy_string_buffer(srv->cond_check_buf, l); buffer_append_string_len(srv->cond_check_buf, CONST_STR_LEN(":")); buffer_append_long(srv->cond_check_buf, sock_addr_get_port(&(srv_sock->addr))); l = srv->cond_check_buf; } else if (!ck_colon) { //请求连接的Host信息包含端口号而条件配置信息块的Host没有包含端口号,因此将请求连接Host的端口号去掉。 /* condition "host" but client send "host:port" */ buffer_copy_string_len(srv->cond_check_buf, l->ptr, val_colon - l->ptr); l = srv->cond_check_buf; } break; default: break; } } else { l = srv->empty_string; } break; } case COMP_HTTP_REMOTE_IP: { //REMOTE adj 遥远的 char *nm_slash; /* handle remoteip limitations * * "10.0.0.1" is provided for all comparisions * * only for == and != we support * * "10.0.0.1/24" */ if ((dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE) && (con->dst_addr.plain.sa_family == AF_INET) && (NULL != (nm_slash = strchr(dc->string->ptr, '/')))) { int nm_bits; long nm; char *err; struct in_addr val_inp; if (*(nm_slash+1) == '\0') { //无分类域间路由选择CIDR(CIDR记法,斜线记法),这里对CIDR格式字符串进行检验 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string); //CIDR格式不对,缺少表示网络前缀位数的数字 return COND_RESULT_FALSE; } /* 函数strtol()声明在头文件stdlib.h内,原型为long int strtol(const char *nptr,char **endptr,int base);用于将参数nptr字符串根据 base指定的进制转换成对应的长整型数。参数base范围从2至36,或0(即默认采用十进制做转换,但遇到如'0x'前置字符则会使用十六进制做转换)。 strtol()会扫描参数nptr字符串,跳过前面的空格字符,知道遇上数字或正负号才开始做转换,在遇到非数字或字符串结束时('\0')结束转换,并将结果返回。 若参数endptr不为NULL,则会将不符合调节而终止的nptr中的字符指针由endptr返回。该函数执行成功返回转换后的长整型数,否则返回ERANGE(表示指定的专函字符串超出合法范围) 并将错误代码存入errno中,此处用于获取端口十进制的整型数。 */ nm_bits = strtol(nm_slash + 1, &err, 10); if (*err) { log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, err); return COND_RESULT_FALSE; } /* take IP convert to the native */ buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr); #ifdef __WIN32 if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) { log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); return COND_RESULT_FALSE; } #else /* 函数inet_ston()声明在头文件sys/scoket.h内,原型为int inet_aton(const char *cp,struct in_addr *inp); 用于将参数cp所指的字符串形式的网络地址 转换成网络地址成网络使用的二进制数形式,然后存于参数inp所指的in_addr结构中。 */ if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) { log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); return COND_RESULT_FALSE; } #endif /* build netmask */ /* 函数htonl()声明在头文件srpa/inet.h内,原型为unint32_t htonl(uint32_t hostlong); 用来将参数hostlong指定的32位无符号长整型由主机字节顺序转换成网络字符顺序。 */ nm = htonl(~((1 << (32 - nm_bits)) - 1)); if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) { //当前连接的客户端IP地址与条件配置信息块的条件设置匹配,按需返回结果 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; } else { //不匹配 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; } } else { l = con->dst_addr_buf; } break; } case COMP_HTTP_SCHEME: l = con->uri.scheme; break; case COMP_HTTP_URL: l = con->uri.path; break; case COMP_HTTP_QUERY_STRING: l = con->uri.query; break; case COMP_SERVER_SOCKET: l = srv_sock->srv_token; break; case COMP_HTTP_REFERER: { data_string *ds; if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) { l = ds->value; } else { l = srv->empty_string; } break; } case COMP_HTTP_COOKIE: { data_string *ds; if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) { l = ds->value; } else { l = srv->empty_string; } break; } case COMP_HTTP_USER_AGENT: { data_string *ds; if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) { l = ds->value; } else { l = srv->empty_string; } break; } case COMP_HTTP_REQUEST_METHOD: { /* get_http_method_name()函数根据当前连接的请求方法(通过分析请求行得知)返回对应的字符串,比如"GET"、"POST"等 */ const char *method = get_http_method_name(con->request.http_method); /* we only have the request method as const char but we need a buffer for comparing */ //为了后面的统一匹配比较,利用该字符串初始化buffer结构体。 buffer_copy_string(srv->tmp_buf, method); l = srv->tmp_buf; break; } default: return COND_RESULT_FALSE; } if (NULL == l) { //当前连接匹配字段为空,则返回假 if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key, "(", l, ") compare to NULL"); } return COND_RESULT_FALSE; } if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key, "(", l, ") compare to ", dc->string); } switch(dc->cond) { case CONFIG_COND_NE: case CONFIG_COND_EQ: if (buffer_is_equal(l, dc->string)) { //相等或不等匹配 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; } else { return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; } break; #ifdef HAVE_PCRE_H /* 正则式匹配需要相应库的支持,GNU/Linux下有两套正则式编程支持库:POSIX库和PCRE库,POSIX库不需要单独安装,能满足一般需求,但是速度稍慢些, 读者查看MAN手册。PCRE库久负盛名,功能强大,匹配速度快,但是可能需要单独安装。关于PCRE库的更多介绍,读者可以查阅站点:http://www.pcre.org/。 此处用的是PCRE库。 */ case CONFIG_COND_NOMATCH: case CONFIG_COND_MATCH: { cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; int n; #ifndef elementsof #define elementsof(x) (sizeof(x) / sizeof(x[0])) #endif n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0, cache->matches, elementsof(cache->matches)); //利用PCRE库函数pcre_exec()执行匹配操作,如果不匹配或执行出错则返回一个负值(其中,不匹配则返回PCRE_ERROR_NOMATCH(该宏值为-1)), //如果匹配成功将返回一个正数。关于函数pcre_exec()的详细说明可以参考说明文档:http://www.pcre.org/prce.txt. cache->patterncount = n; if (n > 0) { //匹配成功 cache->comp_value = l; cache->comp_type = dc->comp; return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE; } else { /* cache is already cleared */ return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE; } break; } #endif default: /* no way */ break; } return COND_RESULT_FALSE; }
int csopen(register Cs_t* state, const char* apath, int op) { register char* path = (char*)apath; register char* b; register char* s; register int n; int fd; char* t; char* u; char* type; char* endtype; char* host; char* endhost; char* serv; char* endserv; char* qual; char* endqual; char* opath; char* user = 0; char* group = 0; char* trust = 0; char* arg = 0; int nfd = -1; int uid = -1; int gid = -1; int sid = -1; int auth = 1; int mode; unsigned long addr; unsigned long port = 0; struct stat st; gid_t groups[NGROUPS_MAX + 1]; char buf[PATH_MAX]; char tmp[PATH_MAX]; if (!path) { errno = EFAULT; return -1; } csprotect(&cs); if (op < 0) op = CS_OPEN_TEST; messagef((state->id, NiL, -8, "open(%s,%o) call", path, op)); /* * blast out the parts */ opath = path; if (pathgetlink(path, buf, sizeof(buf)) <= 0) { if (strlen(path) >= sizeof(buf)) return -1; strcpy(buf, path); } else if ((state->flags & CS_ADDR_LOCAL) && (s = strrchr(buf, '/'))) { /* * dynamic ip assignment can change the addr * underfoot in some implementations so we * double check the local ip here */ strcpy(tmp, buf); if (tokscan(tmp, NiL, "/dev/%s/%s/%s", &type, NiL, &serv) == 3) sfsprintf(buf, sizeof(buf), "/dev/%s/%s/%s", type, csntoa(state, 0), serv); } path = buf; pathcanon(path, 0, 0); errno = ENOENT; strcpy(state->path, path); b = path; if ((*b++ != '/') || !(s = strchr(b, '/'))) return -1; *s++ = 0; if (!streq(b, "dev")) return -1; if (b = strchr(s, '/')) *b++ = 0; if (streq(s, "fdp")) { #if !( CS_LIB_SOCKET_UN || CS_LIB_STREAM || CS_LIB_V10 ) if (access(CS_PROC_FD_TST, F_OK)) { errno = ENODEV; messagef((state->id, NiL, -1, "open: %s: %s: not supported", state->path, s)); return -1; } #endif } else if (!streq(s, "tcp") && !streq(s, "udp")) { messagef((state->id, NiL, -1, "open: %s: %s: invalid type", state->path, s)); return -1; } #if !( CS_LIB_SOCKET || CS_LIB_STREAM || CS_LIB_V10 ) else { errno = ENODEV; messagef((state->id, NiL, -1, "open: %s: %s: not supported", state->path, s)); return -1; } #endif type = s; qual = state->qual; if (!b) host = serv = 0; else { host = b; if (!(s = strchr(b, '/'))) serv = 0; else { *s++ = 0; serv = s; /* * grab the next fd to preserve open semantics */ for (n = 0; n < 10; n++) if ((nfd = dup(n)) >= 0) break; /* * get qual, perm and arg */ mode = S_IRWXU|S_IRWXG|S_IRWXO; if (b = strchr(s, '/')) { *b++ = 0; do { if (*b == '#') { arg = b + 1; break; } if (u = strchr(b, '/')) *u++ = 0; if (s = strchr(b, '=')) *s++ = 0; for (n = 0, t = b; *t; n = HASHKEYPART(n, *t++)); switch (n) { case HASHKEY5('g','r','o','u','p'): group = s ? s : ""; break; case HASHKEY5('l','o','c','a','l'): op |= CS_OPEN_LOCAL; break; case HASHKEY3('n','o','w'): op |= CS_OPEN_NOW; break; case HASHKEY5('o','t','h','e','r'): auth = 0; break; case HASHKEY6('r','e','m','o','t','e'): op |= CS_OPEN_REMOTE; break; case HASHKEY5('s','h','a','r','e'): op |= CS_OPEN_SHARE; break; case HASHKEY5('s','l','a','v','e'): op |= CS_OPEN_SLAVE; break; case HASHKEY4('t','e','s','t'): op |= CS_OPEN_TEST; break; case HASHKEY5('t','r','u','s','t'): op |= CS_OPEN_TRUST; trust = s; break; case HASHKEY4('u','s','e','r'): user = s ? s : ""; break; default: qual += sfsprintf(qual, sizeof(state->qual) - (qual - state->qual) - 1, "%s%s", qual == state->qual ? "" : "-", b); if (s) *(s - 1) = '='; break; } } while (b = u); } } } if (*type != 't') auth = 0; strncpy(state->type, type, sizeof(state->type) - 1); qual = (qual == state->qual) ? (char*)0 : state->qual; messagef((state->id, NiL, -8, "open: type=%s host=%s serv=%s qual=%s", type, host, serv, qual)); if (host) { /* * validate host */ if (!(state->addr = addr = csaddr(state, host))) { if (serv && !(op & CS_OPEN_CREATE) && *type == 't' && (port = csport(state, type, serv)) >= CS_PORT_MIN && port <= CS_PORT_MAX) { /* * attempt proxy connection */ if (nfd >= 0) { close(nfd); nfd = -1; } if ((fd = state->proxy.addr ? csbind(state, type, state->proxy.addr, state->proxy.port, 0L) : reopen(state, csvar(state, CS_VAR_PROXY, 0))) >= 0) { state->proxy.addr = state->addr; state->proxy.port = state->port; n = sfsprintf(tmp, sizeof(tmp), "\n%s!%s!%d\n\n%s\n%s\n0\n-1\n-1\n", type, host, port, csname(state, 0), error_info.id ? error_info.id : state->id); if (cswrite(state, fd, tmp, n) == n && (n = csread(state, fd, tmp, sizeof(tmp), CS_LINE)) >= 2) { if (tmp[0] == '0' && tmp[1] == '\n') return fd; if (error_info.trace <= -4 && n > 2) { s = tmp; s[n - 1] = 0; while (*s && *s++ != '\n'); messagef((state->id, NiL, -4, "%s error message `%s'", csvar(state, CS_VAR_PROXY, 0), s)); } } close(fd); } } #ifdef EADDRNOTAVAIL errno = EADDRNOTAVAIL; #else errno = ENOENT; #endif goto bad; } if (op & CS_OPEN_LOCAL) { state->flags |= CS_ADDR_LOCAL; state->flags &= ~CS_ADDR_REMOTE; } if (op & CS_OPEN_NOW) state->flags |= CS_ADDR_NOW; if ((op & (CS_OPEN_AGENT|CS_OPEN_REMOTE)) == CS_OPEN_REMOTE) { state->flags |= CS_ADDR_REMOTE; state->flags &= ~CS_ADDR_LOCAL; } if (op & CS_OPEN_SHARE) state->flags |= CS_ADDR_SHARE; if (op & CS_OPEN_SLAVE) state->flags |= CS_DAEMON_SLAVE; if (op & CS_OPEN_TEST) state->flags |= CS_ADDR_TEST; if (op & CS_OPEN_TRUST) state->flags |= CS_ADDR_TRUST; if ((state->flags & CS_ADDR_REMOTE) && (!serv || !strneq(serv, CS_SVC_INET, sizeof(CS_SVC_INET) - 1) && (strtol(serv, &t, 0), *t))) return agent(state, state->host, state->user, state->path); if (s = user) { n = geteuid(); if (*s) { if ((uid = struid(s)) < 0) { uid = strtol(s, &t, 0); if (*t) { errno = EACCES; goto bad; } } if (n && uid != n) { errno = EACCES; goto bad; } } else uid = n; mode &= ~(S_IRWXG|S_IRWXO); } if (s = group) { n = getegid(); if (*s) { if ((gid = strgid(s)) < 0) { gid = strtol(s, &t, 0); if (*t) { errno = EACCES; goto bad; } } if (geteuid() && gid != n) { for (n = getgroups(elementsof(groups), groups); n >= 0; n--) if (gid == groups[n]) break; if (n < 0) { errno = EACCES; goto bad; } } } else gid = n; mode &= ~S_IRWXO; } if (s = trust) { if (!*s) sid = geteuid(); else if ((sid = struid(s)) < 0) { sid = strtol(s, &t, 0); if (*t) { errno = EACCES; goto bad; } } } if (state->flags & CS_ADDR_SHARE) host = CS_HOST_SHARE; else { host = state->host; if (!(state->flags & CS_ADDR_LOCAL)) { if (*type == 'f') { errno = ENODEV; goto bad; } if (op & CS_OPEN_CREATE) { errno = EROFS; goto bad; } } if (serv && !qual && *type != 'f' && (port = csport(state, type, serv)) != CS_PORT_INVALID) { if (op & CS_OPEN_CREATE) addr = 0; else if (port == CS_PORT_RESERVED || port == CS_PORT_NORMAL) goto bad; if (nfd >= 0) { close(nfd); nfd = -1; } state->control = 0; if ((fd = csbind(state, type, addr, port, 0L)) >= 0) { if (mode != (S_IRWXU|S_IRWXG|S_IRWXO) && csauth(state, fd, NiL, NiL)) { close(fd); return -1; } return fd; } } } } /* * get the mount dir prefix */ if (opath == (b = path = state->mount)) { #ifdef ELOOP errno = ELOOP; #else errno = EINVAL; #endif goto bad; } if (*type == 'f') { if (host && !(state->flags & CS_ADDR_LOCAL)) { errno = ENODEV; goto bad; } b += sfsprintf(b, sizeof(state->mount) - (b - path), "%s", csvar(state, CS_VAR_LOCAL, 0)); if ((op & CS_OPEN_CREATE) && eaccess(path, X_OK) && (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO))) goto bad; } else { if (op & CS_OPEN_TRUST) { if (!pathaccess(csvar(state, CS_VAR_TRUST, 1), csvar(state, CS_VAR_SHARE, 1), NiL, PATH_EXECUTE, b, sizeof(state->mount) - (b - state->mount))) goto bad; } else if (!pathpath(csvar(state, CS_VAR_SHARE, 0), "", PATH_EXECUTE, b, sizeof(state->mount) - (b - state->mount))) goto bad; b += strlen(b); } /* * add the type */ b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%s", type); if (!host) { *(state->control = b + 1) = 0; if (nfd >= 0) close(nfd); if ((fd = open(path, O_RDONLY)) < 0) { mkmount(state, S_IRWXU|S_IRWXG|S_IRWXO, -1, -1, NiL, NiL, NiL); fd = open(path, O_RDONLY); } if (fd < 0) messagef((state->id, NiL, -1, "open: %s: %s: open error", state->path, path)); return fd; } endtype = b; /* * add the host */ if (strlen(host) <= CS_MNT_MAX) b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%s", host); else { s = csntoa(state, addr); if (strlen(s) <= CS_MNT_MAX) b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%s", s); else { unsigned char* a = (unsigned char*)&addr; b += sfsprintf(b, sizeof(state->mount) - (b - path), "/0x%X.%X.%X.%X", a[0], a[1], a[2], a[3]); } } messagef((state->id, NiL, -8, "%s:%d host=`%s' path=`%s'", __FILE__, __LINE__, host, path)); if (!serv) { *(state->control = b + 1) = 0; if (nfd >= 0) close(nfd); if ((fd = open(path, O_RDONLY)) < 0) messagef((state->id, NiL, -1, "open: %s: %s: open error", state->path, path)); return fd; } endhost = b; /* * add the service */ sfsprintf(b, sizeof(state->mount) - (b - path), "%s/%s/%s/%s%s", CS_SVC_DIR, type, serv, serv, CS_SVC_SUFFIX); if (!pathpath(b, "", PATH_ABSOLUTE|PATH_EXECUTE, tmp, sizeof(tmp)) || stat(tmp, &st)) op |= CS_OPEN_TEST; else { *strrchr(tmp, '/') = 0; if (!(op & CS_OPEN_TRUST)) sid = st.st_uid; if (!st.st_size) op |= CS_OPEN_TEST; } b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%s", serv); endserv = b; /* * add the qualifier and perm */ if (sid >= 0) b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%d-", sid); else b += sfsprintf(b, sizeof(state->mount) - (b - path), "/-"); if (uid >= 0) b += sfsprintf(b, sizeof(state->mount) - (b - path), "%d-", uid); else if (gid >= 0) b += sfsprintf(b, sizeof(state->mount) - (b - path), "-%d", gid); else b += sfsprintf(b, sizeof(state->mount) - (b - path), "-"); #if limit_qualifier_length endqual = endserv + CS_MNT_MAX + 1; #else endqual = state->mount + sizeof(state->mount) - 1; #endif if (qual) { if (b < endqual) *b++ = '-'; while (b < endqual && *qual) *b++ = *qual++; } if (*type == 't' && !auth) { if (b >= endqual) b--; *b++ = CS_MNT_OTHER; } /* * add in the connect stream control */ *b++ = '/'; *b = CS_MNT_STREAM; strcpy(b + 1, CS_MNT_TAIL); messagef((state->id, NiL, -8, "%s:%d %s", __FILE__, __LINE__, state->mount)); state->control = b; /* * create the mount subdirs if necessary */ if ((op & CS_OPEN_CREATE) && mkmount(state, mode, uid, gid, endserv, endhost, endtype)) goto bad; mode &= S_IRWXU|S_IRWXG|S_IRWXO; if (nfd >= 0) { close(nfd); nfd = -1; } if (op & CS_OPEN_MOUNT) { messagef((state->id, NiL, -1, "open(%s,%o) = %d, mount = %s", state->path, op, state->mount)); return 0; } if (*type == 'f') { /* * {fdp} */ if ((fd = doattach(state, path, op, mode, user, opath, tmp, serv, b)) < 0) return -1; } else { /* * {tcp,udp} */ messagef((state->id, NiL, -8, "%s:%d %s", __FILE__, __LINE__, state->mount)); if ((fd = reopen(state, path)) < 0) { /* * check for old single char cs mount */ *(state->control + 1) = 0; if ((fd = reopen(state, path)) < 0) messagef((state->id, NiL, -1, "open: %s: %s: reopen error", state->path, path)); *(state->control + 1) = CS_MNT_TAIL[0]; } if (op & CS_OPEN_CREATE) { if (fd >= 0) { close(fd); errno = EEXIST; return -1; } if (errno != ENOENT && errno != ENOTDIR) return -1; sigcritical(1); *state->control = CS_MNT_LOCK; if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0)) < 0) { if (stat(path, &st)) { messagef((state->id, NiL, -1, "open: %s: %s: creat error", state->path, path)); goto unblock; } if ((CSTIME() - (unsigned long)st.st_ctime) < 2 * 60) { errno = EEXIST; messagef((state->id, NiL, -1, "open: %s: %s: another server won the race", state->path, path)); goto unblock; } if (remove(path)) { messagef((state->id, NiL, -1, "open: %s: %s: remove error", state->path, path)); goto unblock; } if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0)) < 0) { messagef((state->id, NiL, -1, "open: %s: %s: creat error", state->path, path)); goto unblock; } } close(fd); if (!port && (n = strtol(serv, &t, 0)) && t > serv && !*t) port = n; else if (geteuid()) port = CS_NORMAL; else port = CS_RESERVED; if ((fd = csbind(state, type, 0L, port, 0L)) >= 0) { *state->control = CS_MNT_STREAM; remove(path); if (pathsetlink(cspath(state, fd, 0), path)) { messagef((state->id, NiL, -1, "open: %s: %s: link error", cspath(state, fd, 0), path)); close(fd); fd = -1; } } unblock: *state->control = CS_MNT_LOCK; remove(path); sigcritical(0); *state->control = CS_MNT_STREAM; if (fd < 0) return -1; } else if (fd < 0 && ((op & CS_OPEN_TEST) || initiate(state, user, opath, tmp, serv) || (fd = reopen(state, path)) < 0)) { messagef((state->id, NiL, -1, "open: %s: %s: reopen/initiate error", state->path, path)); return -1; } else if (!(op & CS_OPEN_AGENT)) { *state->control = CS_MNT_AUTH; n = csauth(state, fd, path, arg); *state->control = CS_MNT_STREAM; if (n) { close(fd); messagef((state->id, NiL, -1, "open: %s: %s: authentication error", state->path, path)); return -1; } } } /* * fd is open at this point * make sure its not a bogus mount */ if (mode != (S_IRWXU|S_IRWXG|S_IRWXO)) { *state->control = 0; n = stat(path, &st); *state->control = CS_MNT_STREAM; if (n) { messagef((state->id, NiL, -1, "open: %s: %s: stat error", state->path, path)); close(fd); return -1; } if (uid >= 0 && st.st_uid != uid || gid >= 0 && st.st_gid != gid) { close(fd); errno = EPERM; messagef((state->id, NiL, -1, "open: %s: %s: uid/gid error", state->path, path)); return -1; } } return fd; bad: if (nfd >= 0) close(nfd); return -1; }
static Dssmeth_t* textmeth(const char* name, const char* options, const char* schema, Dssdisc_t* disc, Dssmeth_t* ometh) { register Text_t* text; register Dssmeth_t* meth; register Cxvariable_t* var; register char* s; register char* t; register char* f; register int c; char* d; int p; int index; if (options) { if (dssoptlib(ometh->cx->buf, &dss_lib_text, usage, disc)) goto drop; s = sfstruse(ometh->cx->buf); for (;;) { switch (optstr(options, s)) { case '?': if (disc->errorf) (*disc->errorf)(NiL, disc, ERROR_USAGE|4, "%s", opt_info.arg); goto drop; case ':': if (disc->errorf) (*disc->errorf)(NiL, disc, 2, "%s", opt_info.arg); goto drop; } break; } } if (!schema || !*schema) return ometh; if (!(meth = newof(0, Dssmeth_t, 1, sizeof(Text_t) + strlen(name) + 2 * strlen(schema) + 2))) { free(meth); if (disc->errorf) (*disc->errorf)(NiL, disc, 2, "out of space"); return 0; } *meth = *ometh; meth->data = text = (Text_t*)(meth + 1); text->format = strcopy(text->name, name) + 1; index = 0; s = (char*)schema; f = text->format; for (;;) { switch (c = *s++) { case 0: break; case '%': *f++ = '%'; var = 0; switch (c = *s++) { case 0: goto invalid; case 'h': case 'l': case 'L': case '+': case '-': case '.': case '_': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': continue; case '%': *f++ = '%'; continue; case '(': t = f; d = 0; p = 1; for (;;) { switch (c = *s++) { case 0: goto invalid; case '(': p++; *t++ = c; continue; case ')': if (!--p) break; *t++ = c; continue; case ':': if (d) *t++ = c; else { *t++ = 0; d = t; } continue; default: *t++ = c; continue; } break; } *t = 0; if (dtmatch(meth->cx->variables, f)) { if (disc->errorf) (*disc->errorf)(NiL, disc, 2, "%s: duplicate field", f); goto drop; } if (!(var = newof(0, Cxvariable_t, 1, t - f + 1))) { if (disc->errorf) (*disc->errorf)(NiL, disc, 2, "out of space"); goto drop; } var->index = index; t = strcopy((char*)(var->name = (char*)(var + 1)), f); if (d) var->description = strcpy(t + 1, d); break; } for (;;) { switch (c = *s++) { case 0: goto invalid; case 'h': case 'l': case 'L': case '+': case '-': case '.': case '_': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': continue; } break; } if (var) { switch (c) { case 'd': case 'f': case 'g': case 'n': case 'o': case 'u': case 'x': var->type = (Cxtype_t*)"number"; break; case 'i': var->type = (Cxtype_t*)"ipaddr_t"; break; case 's': var->type = (Cxtype_t*)"string"; break; case 't': var->type = (Cxtype_t*)"time_t"; break; default: if (disc->errorf) (*disc->errorf)(NiL, disc, 2, "%c: invalid field format >>>%s", c, s - 1); goto drop; } if (cxaddvariable(meth->cx, var, disc)) goto drop; } index++; *f++ = c; continue; case ' ': case '\t': case '\n': if (f == text->format || *(f - 1) != ' ') *f++ = ' '; continue; default: *f++ = c; continue; } break; } if (!(text->vars = index)) goto invalid; *f = 0; dtinsert(meth->formats, &text_format); for (c = 0; c < elementsof(local_callouts); c++) if (cxaddcallout(meth->cx, &local_callouts[c], disc)) return 0; return meth; invalid: if (disc->errorf) (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: invalid schema", schema); drop: free(meth); return 0; }
static void output(struct termios *sp, int flags) { const Tty_t *tp; struct termios tty; register int delim = ' '; register int i,off,off2; char schar[2]; unsigned int ispeed = cfgetispeed(sp); unsigned int ospeed = cfgetospeed(sp); if(flags&G_FLAG) { gout(sp); return; } tty = *sp; sane(&tty); for(i=0; i < elementsof(Ttable); i++) { tp= &Ttable[i]; if(tp->flags&IG) { if(tp->flags&NL) sfputc(sfstdout,'\n'); continue; } switch(tp->type) { case BIT: case BITS: off = off2 = 1; switch(tp->field) { case C_FLAG: if(sp->c_cflag&tp->mask) off = 0; if(tty.c_cflag&tp->mask) off2 = 0; break; case I_FLAG: if(sp->c_iflag&tp->mask) off = 0; if(tty.c_iflag&tp->mask) off2 = 0; break; case O_FLAG: if((sp->c_oflag&tp->mask)==tp->val) off = 0; if(tty.c_oflag&tp->mask) off2 = 0; break; case L_FLAG: if(sp->c_lflag&tp->mask) off = 0; if(tty.c_lflag&tp->mask) off2 = 0; } if(tp->flags&NL) delim = '\n'; if(!flags && off==off2) continue; if(!off) sfprintf(sfstdout,"%s%c",tp->name,delim); else if(tp->type==BIT) sfprintf(sfstdout,"-%s%c",tp->name,delim); delim = ' '; break; case CHAR: off = sp->c_cc[tp->mask]; if(tp->flags&NL) delim = '\n'; if(!flags && off==(unsigned char)tty.c_cc[tp->mask]) continue; if(off==_POSIX_VDISABLE) sfprintf(sfstdout,"%s = <undef>;%c",tp->name,delim); else if(isprint(off&0xff)) sfprintf(sfstdout,"%s = %c;%c",tp->name,off,delim); else #if CC_NATIVE == CC_ASCII sfprintf(sfstdout,"%s = ^%c;%c",tp->name,off==0177?'?':(off^0100),delim); #else { off = ccmapc(off, CC_NATIVE, CC_ASCII); sfprintf(sfstdout,"%s = ^%c;%c",tp->name,off==0177?'?':ccmapc(off^0100,CC_ASCII,CC_NATIVE),delim); } #endif delim = ' '; break; case SIZE: if((sp->c_cflag&CSIZE)!=tp->mask) continue; if(flags || (sp->c_cflag&CSIZE) != (tty.c_cflag&CSIZE)) sfprintf(sfstdout,"%s ",tp->name); break; case SPEED: if(tp->mask==ispeed) { if(ispeed!=ospeed) schar[0]='i'; else schar[0]=0; } else if(tp->mask==ospeed) schar[0]='o'; else continue; schar[1] = 0; #ifdef TIOCSWINSZ { struct winsize win; off = ioctl(0,TIOCGWINSZ,&win); if(off>=0) sfprintf(sfstdout,"%sspeed %s baud; rows %d; columns %d;\n",schar,tp->name,win.ws_row,win.ws_col); } if(off<0) #endif sfprintf(sfstdout,"%sspeed %s baud;\n",schar,tp->name); } } if(delim=='\n') sfputc(sfstdout,'\n'); }