📄 parser.c++
字号:
return (true); } } else syntaxError(fxStr::format( "bad time specification (expecting %d digits)", len)); } return (false);}boolHylaFAXServer::BOOLEAN(bool& b){ if (getToken(T_STRING, "boolean")) { tokenBody.raisecase(); if (tokenBody == "YES") { b = true; return (true); } else if (tokenBody == "NO") { b = false; return (true); } else syntaxError("invalid boolean value, use YES or NO"); } return (false);}boolHylaFAXServer::checkToken(Token wanted){ Token t = nextToken(); if (t != wanted) { pushToken(t); return (false); } else return (true);}boolHylaFAXServer::getToken(Token wanted, const char* expected){ Token t = nextToken(); if (t != wanted) { if (t == T_LEXERR) syntaxError("unmatched quote mark"); else syntaxError(fxStr::format("expecting %s", expected)); return (false); } else return (true);}bool HylaFAXServer::SPACE() { return getToken(T_SP, "<SP>"); }bool HylaFAXServer::COMMA() { return getToken(T_COMMA, "\",\""); }bool HylaFAXServer::CRLF() { return getToken(T_CRLF, "<CRLF>"); }bool HylaFAXServer::opt_CRLF() { return checkToken(T_CRLF); }boolHylaFAXServer::opt_STRING(fxStr& s){ if (checkToken(T_STRING)) { s = tokenBody; return (true); } else return (false);}boolHylaFAXServer::STRING(fxStr& s, const char* what){ if (getToken(T_STRING, what != NULL ? what : "<STRING>")) { s = tokenBody; return (true); } else return (false);}boolHylaFAXServer::multi_STRING(fxStr& s){ if (!STRING(s)) return (false); for (;;) { switch (nextToken()) { case T_CRLF: pushToken(T_CRLF); return (true); case T_COMMA: s.append(','); break; case T_STRING: s.append(tokenBody); break; case T_SP: s.append(' '); break; case T_LEXERR: syntaxError("unmatched quote mark"); return (false); } }}boolHylaFAXServer::checkNUMBER(const char* cp){ if (cp[0] == '-' || cp[0] == '+') cp++; for (; *cp; cp++) if (!isdigit(*cp)) { syntaxError("invalid number"); return (false); } return (true);}boolHylaFAXServer::NUMBER(long& n){ if (!getToken(T_STRING, "decimal number")) { return (false); } else if (!checkNUMBER(tokenBody)) { return (false); } else { n = strtol(tokenBody, NULL, 0); return (true); }}voidHylaFAXServer::syntaxError(const char* msg){ const char* cp = strchr(cbuf, '\0'); if (cp[-1] == '\n') cp--; reply(500, "'%.*s': Syntax error, %s.", cp-cbuf, cbuf, msg);}/* * Lexical Scanner. *//* * Return the next byte of data from the control channel. * If no data is available, either wait for new data to * be received or return EOF. */intHylaFAXServer::getChar(bool waitForInput){ if (recvCC <= 0) { // enable non-blocking i/o on control channel (void) fcntl(STDIN_FILENO, F_SETFL, ctrlFlags | O_NONBLOCK);again: do { recvCC = Sys::read(STDIN_FILENO, recvBuf, sizeof (recvBuf)); } while (recvCC < 0 && errno == EINTR); if (recvCC < 0 && errno == EWOULDBLOCK && waitForInput) { Dispatcher& disp = Dispatcher::instance(); disp.startTimer(idleTimeout, 0, this); for (state |= S_WAITDATA; IS(WAITDATA); disp.dispatch()) ; disp.stopTimer(this); goto again; } (void) fcntl(STDIN_FILENO, F_SETFL, ctrlFlags); if (recvCC <= 0) { if (recvCC == 0) { // no more input coming, remove handler Dispatcher::instance().unlink(STDIN_FILENO); dologout(0); // XXX what about server interactions??? } return (EOF); } recvNext = 0; } recvCC--; return recvBuf[recvNext++] & 0377;}/* * Push back control channel data. */voidHylaFAXServer::pushCmdData(const char* data, int n){ if ((unsigned) recvNext + n > sizeof (recvBuf)) { logError("No space to push back urgent data \"%.*s\"", n, data); return; } if (recvNext < n) { // not enough space, copy existing data memmove(&recvBuf[n], &recvBuf[recvNext], recvCC); recvNext = 0; } else // space available, just adjust recvNext recvNext -= n; memcpy(&recvBuf[recvNext], data, n); recvCC += n;}/* * Return the next line of data received on the control * channel, ignoring any Telnet protocol command sequences. */boolHylaFAXServer::getCmdLine(char* s, int n, bool waitForInput){ char* cp = s; cpos = 0; while (n > 1) { int c = getChar(cp != s || waitForInput); if (c == EOF) return (false); if (c == IAC) { // telnet protocol command c = getChar(true); if (c == EOF) return (false); switch (c&0377) { case WILL: case WONT: c = getChar(true); // telnet option if (c == EOF) return (false); printf("%c%c%c", IAC, DONT, c&0377); (void) fflush(stdout); continue; case DO: case DONT: c = getChar(true); // telnet option if (c == EOF) return (false); printf("%c%c%c", IAC, WONT, c&0377); (void) fflush(stdout); continue; case IAC: // <IAC><IAC> -> <IAC> break; default: // ignore command continue; } } if (c == '\n') { // convert \r\n -> \n if (cp > s && cp[-1] == '\r') cp[-1] = '\n'; else *cp++ = '\n', n--; break; } *cp++ = c, n--; } *cp = '\0'; if (TRACE(PROTOCOL)) logDebug("command: %s", s); return (true);}voidHylaFAXServer::timerExpired(long, long){ reply(421, "Timeout (%d seconds): closing control connection.", idleTimeout); if (TRACE(SERVER)) { time_t now = Sys::now(); logInfo("User %s timed out after %d seconds at %.24s" , IS(LOGGEDIN) ? (const char*) the_user : "(noone)" , idleTimeout , asctime(cvtTime(now)) ); } dologout(1);}TokenHylaFAXServer::nextToken(void){ if (pushedToken != T_NIL) { Token t = pushedToken; pushedToken = T_NIL; return (t); } switch (cbuf[cpos]) { case ' ': while (cbuf[++cpos] == ' ') // compress multiple spaces ; return (T_SP); case '\n': cpos++; return (T_CRLF); case ',': cpos++; return (T_COMMA); case '"': /* * Parse quoted string and deal with \ escapes. */ tokenBody.resize(0); for (;;) { int c = cbuf[++cpos]; if (c == '"') { cpos++; return (T_STRING); } if (c == '\n') // unmatched quote mark return (T_LEXERR); if (c == '\\') { // \ escape handling c = cbuf[++cpos]; if (isdigit(c)) { // \nnn octal escape int v = c - '0'; if (isdigit(c = cbuf[cpos+1])) { cpos++, v = (v << 3) + (c - '0'); if (isdigit(c = cbuf[cpos+1])) cpos++, v = (v << 3) + (c - '0'); } c = v; } } tokenBody.append(c); } /*NOTREACHED*/ } int base = cpos; do { cpos++; } while (cbuf[cpos] != ' ' && cbuf[cpos] != '\n' && cbuf[cpos] != ','); tokenBody = fxStr(&cbuf[base], cpos - base); return (T_STRING);}voidHylaFAXServer::helpCmd(const tab* ctab, const char* s){ const char* type; u_int NCMDS; if (ctab == sitetab) { type = "SITE "; NCMDS = N(sitetab); } else if (ctab == parmtab) { type = "JPARM "; NCMDS = N(parmtab); } else { type = ""; NCMDS = N(cmdtab); } int width = 0; const tab* c = ctab; for (u_int n = NCMDS; n != 0; c++, n--) { int len = strlen(c->name); if (len > width) width = len; } width = (width + 8) &~ 7; if (s == NULL) { lreply(214, "The following %scommands are recognized %s.", type, "(* =>'s unimplemented)"); int columns = 76 / width; if (columns == 0) columns = 1; int lines = (NCMDS + columns - 1) / columns; for (int i = 0; i < lines; i++) { printf(" "); for (int j = 0; j < columns; j++) { c = &ctab[j*lines + i]; printf("%s%c", c->name, !c->implemented ? '*' : ' '); if (c + lines >= &ctab[NCMDS]) break; int w = strlen(c->name) + 1; while (w < width) { putchar(' '); w++; } } printf("\r\n"); } (void) fflush(stdout); reply(214, "Direct comments to %s.", (const char*) faxContact); return; } c = lookup(ctab, NCMDS, s); if (c == NULL) { reply(502, "Unknown command %s.", s); return; } if (c->implemented) reply(214, "Syntax: %s%s %s", type, c->name, c->help); else reply(214, "%s%-*s\t%s; unimplemented.", type, width, c->name, c->help);}voidHylaFAXServer::logcmd(Token t, const char* fmt ...){ if (TRACE(PROTOCOL)) { const char* name = cmdToken(t); if (!name) name = siteToken(t); if (!name) name = "???"; if (fmt != NULL) { va_list ap; va_start(ap, fmt); vlogInfo(fxStr::format("%s %s", name, fmt), ap); va_end(ap); } else logInfo("%s", name); }}voidHylaFAXServer::cmdFailure(Token t, const char* why){ if (TRACE(SERVER)) { const char* cp = cmdToken(t); if (!cp) cp = siteToken(t); if (cp) logInfo("%s cmd failure - %s", cp, why); else logInfo("#%u cmd failure - %s", t, why); }}boolHylaFAXServer::checklogin(Token t){ if (!IS(LOGGEDIN)) { cmdFailure(t, "not logged in"); reply(530, "Please login with USER and PASS."); return (false); } else return (true);}boolHylaFAXServer::checkadmin(Token t){ if (checklogin(t)) { if (IS(PRIVILEGED)) return (true); cmdFailure(t, "user is not privileged"); reply(530, "Please use ADMIN to establish administrative privileges."); } return (false);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -