int main(int argc, char** argv) { Css_t* css; Cssfd_t* fp; Connection_t* con; char* e; State_t state; NoP(argc); error_info.id = "css"; memset(&state, 0, sizeof(state)); state.disc.version = CSS_VERSION; state.disc.flags = CSS_DAEMON|CSS_ERROR|CSS_INTERRUPT; state.disc.acceptf = acceptf; state.disc.actionf = actionf; state.disc.errorf = errorf; state.disc.exceptf = exceptf; for (;;) { switch (optget(argv, usage)) { case 't': state.disc.timeout = strelapsed(opt_info.arg, &e, 1); if (*e) error(3, "%s: invalid timeout value", opt_info.arg); state.disc.flags |= CSS_DORMANT; continue; case '?': error(ERROR_USAGE|4, "%s", opt_info.arg); continue; case ':': error(2, "%s", opt_info.arg); continue; } break; } argv += opt_info.index; if (!argv[0] || !argv[1]) error(ERROR_USAGE|4, "%s", optusage(NiL)); if (!(state.tmp = sfstropen())) error(ERROR_SYSTEM|3, "out of space [tmp stream]"); if (!(state.proc = procopen(argv[1], argv + 1, NiL, NiL, PROC_READ|PROC_WRITE))) error(ERROR_SYSTEM|3, "%s: cannot execute", argv[1]); if (!(css = cssopen(argv[0], &state.disc))) return 1; if (!(fp = cssfd(css, state.proc->rfd, CS_POLL_READ))) error(ERROR_SYSTEM|3, "%s: cannot poll output", argv[1]); if (!(con = newof(0, Connection_t, 1, 0))) error(ERROR_SYSTEM|3, "out of space"); fp->data = con; con->service = 1; csspoll(CS_NEVER, 0); return 1; }
static int note(Css_t* css, register Connection_t* to, int log, char* s, size_t n, int force, Cssdisc_t* disc) { register State_t* state = (State_t*)disc; ssize_t z; if ((force || to->blocked[log] < 0) && (z = data(state, to, s, n, force)) != n) { if (!force && !state->logged) { state->logged = 1; if (!state->logs[log].sp) { state->logs[log].name[0] = '0' + log; remove(state->logs[log].name); if (!(state->logs[log].sp = sfopen(NiL, state->logs[log].name, "r+"))) error(ERROR_SYSTEM|3, "%s: cannot create message log", state->logs[log].name); message((-1, "[%d] %s: create log", __LINE__, state->logs[log].name)); } message((-1, "[%d] %s: %d log", __LINE__, state->logs[log].name, to->fp->fd)); if (sfwrite(state->logs[log].sp, s, n) != n) error(ERROR_SYSTEM|3, "%s: log file write error", state->logs[log].name); if ((state->logs[log].offset += n) >= HOG && !state->logs[!log].sp) state->log = !log; } if (to->blocked[log] < 0) { message((-1, "[%d] %s: block", __LINE__, state->logs[log].name)); state->logs[log].blocked++; } to->blocked[log] = state->logs[log].offset - n + z; message((-1, "[%d] %s: %d offset %I*d", __LINE__, state->logs[log].name, to->fp->fd, sizeof(to->blocked[log]), to->blocked[log])); cssfd(css, to->fp->fd, CS_POLL_READ|CS_POLL_WRITE); return 0; } if (to->blocked[log] >= 0) { message((-1, "[%d] %s: %d unblock", __LINE__, state->logs[log].name, to->fp->fd)); to->blocked[log] = -1; if (!--state->logs[log].blocked) { sfclose(state->logs[log].sp); state->logs[log].sp = 0; state->logs[log].offset = 0; remove(state->logs[log].name); message((-1, "[%d] %s: clear", __LINE__, state->logs[log].name)); } } return 1; }
static int actionf(register Css_t* css, register Cssfd_t* fp, Cssdisc_t* disc) { register State_t* state = (State_t*)disc; register Connection_t* con; register char* s; register char* t; int n; int i; switch (fp->status) { case CS_POLL_CLOSE: if (con = (Connection_t*)fp->data) { if (con->service) error(ERROR_SYSTEM|3, "service termination exit"); free(con); } return 0; case CS_POLL_READ: con = (Connection_t*)fp->data; if ((n = csread(css->state, fp->fd, buf, sizeof(buf) - 1, CS_LINE)) <= 0) { if (con->service) error(ERROR_SYSTEM|3, "service termination exit"); return -1; } buf[n] = 0; for (s = buf; isspace(*s); s++); if (con->service) { for (i = 0; isdigit(*s); i = i * 10 + *s++ - '0'); for (; isspace(*s); s++); if (*s && cssfd(css, i, 0)) { n -= s - buf; if (cswrite(css->state, i, s, n) != n) cssfd(css, i, CS_POLL_CLOSE); } } else if (*s == '!') { if ((n -= ++s - buf) > 0 && cswrite(css->state, state->proc->wfd, s, n) != n) return -1; } else { for (t = s; *t && !isspace(*t); t++); for (; isspace(*t); t++); if (*s == 'Q' && !*t) { if (con->id.uid == geteuid()) error(3, "service quit exit"); } else { n = sfprintf(state->tmp, "%-.*s%d %s", t - s, s, fp->fd, t); if (!(s = sfstruse(state->tmp))) return -1; if (cswrite(css->state, state->proc->wfd, s, n) != n) return -1; } } return 1; } return 0; }