TEST test_sdiffstore() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; char *m1 = "mymember", *m2 = "member2", *s1 = "myset", *s2 = "myset2", *t = "target"; sadd(context, s1, m1); sadd(context, s1, m2); sadd(context, s2, m1); sadd(context, s2, "meh"); rliteReply* reply; { char* argv[100] = {"sdiffstore", t, s1, s2, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"smembers", t, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 1); EXPECT_REPLY_STR(reply->element[0], m2, strlen(m2)); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
TEST test_srem() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; char *m1 = "mymember", *m2 = "member2"; sadd(context, "myset", m1); sadd(context, "myset", m2); rliteReply* reply; { char* argv[100] = {"srem", "myset", m1, "other", m2, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 2); rliteFreeReplyObject(reply); } { char* argv[100] = {"exists", "mykey", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 0); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
TEST test_srandmember_10_non_unique() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; long i; char *m1 = "mymember", *m2 = "member2"; sadd(context, "myset", m1); sadd(context, "myset", m2); rliteReply* reply; { char* argv[100] = {"srandmember", "myset", "-10", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 10); for (i = 0; i < 10; i++) { if (!(reply->element[i]->len == (int)strlen(m1) && memcmp(reply->element[i]->str, m1, reply->element[i]->len) == 0) && !(reply->element[i]->len == (int)strlen(m2) && memcmp(reply->element[i]->str, m2, reply->element[i]->len) == 0)) { FAIL(); } } rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
int indexNrOffset(int IndexNr,char Type[]) { if (strcmp(Type,"Url") == 0) { return sadd(IndexNr +1,63); } else if (strcmp(Type,"Anchor") == 0) { return sadd(IndexNr +2,63); } else { return IndexNr; } }
slist * get_interface_names() { slist *sv; pcap_if_t *devs = NULL; pcap_if_t *dev; int ret; sv = sinit(); if(sv == NULL) return NULL; ret = pcap_findalldevs(&devs, NULL); if(ret) { sfree(sv); return NULL; } for(dev = devs; dev; dev = dev->next) { if(sadd(sv, dev->name) == -1) { sfree(sv); sv = NULL; break; } } pcap_freealldevs(devs); return sv; }
bool xRedisClient::sinterstore(const RedisDBIdx& des_dbi, const KEY& destinationkey, const DBIArray& vdbi, const KEYS& vkey, int64_t& count) { VALUES sValue; if (!sinter(vdbi, vkey, sValue)) { return false; } return sadd(des_dbi, destinationkey, sValue, count); }
size_t Ran::complexity(bir mults) const { bix multV = 0; /* initialize number of possibly patterns */ for (auto it : m_subs) { /* for each whole range pair */ const csc bufI0 = dynamic_cast<Base*>(hits[2*i+0])->rand(begin(mults), end(mults)); // sub pattern const csc bufI1 = dynamic_cast<Base*>(hits[2*i+1])->rand(begin(mults), end(mults)); // sub pattern const size_t lenI0 = bufI0.size(); const size_t lenI1 = bufI1.size(); if (lenI0 == lenI1) { switch (lenI0) { case 1: multV += bufI1[0] - bufI0[0] + 1; /* calculate inclusive span */ ret = 1; break; default: std::cerr << "Cannot handle case for ret == " << lenI0 << std::endl; break; } } else { PERR("Cannot handle case for lenI0 != lenI1\n"); } } if (hits.size() % 2 == 1) { const size_t i = hits.size() - 1; multV = sadd(multV, sub->complexity(mults)); } return multV; }
slist * get_interface_names() { struct ifaddrs *ifap = NULL; struct ifaddrs *ifp; slist *sl; sl = sinit(); if(sl == NULL) return NULL; if(getifaddrs(&ifap)) { sfree(sl); return NULL; } for(ifp = ifap; ifp; ifp = ifp->ifa_next) { if(ifp->ifa_addr == 0 || ifp->ifa_addr->sa_family != AF_INET) continue; if(sadd(sl, ifp->ifa_name) == -1) { sfree(sl); sl = NULL; break; } } freeifaddrs(ifap); return sl; }
bool xRedisClient::sunionstore(const RedisDBIdx& dbi, const KEY& deskey, const DBIArray& vdbi, const KEYS& vkey, int64_t& count) { VALUES sValue; if (!dbi.mIOFlag) { SetIOtype(dbi, MASTER, true); } if (!sunion(vdbi, vkey, sValue)) { return false; } return sadd(dbi, deskey, sValue, count); }
void text(int t, char *p1) /* convert text string p1 of type t */ { int c; char *p; tbl *tp; yyval = salloc(); ebase[yyval] = 0; eht[yyval] = EM(1.0, ps); /* ht in ems of orig size */ lfont[yyval] = rfont[yyval] = ROM; lclass[yyval] = rclass[yyval] = OTHER; if (t == QTEXT) { for (p = p1; *p; p++) /* scan for embedded \f's */ if (*p == '\\' && *(p+1) == 'f') break; if (*p) /* if found \f, leave it alone and hope */ p = p1; else { sprintf(cs, "\\f%s%s\\fP", ftp->name, p1); p = cs; } } else if (t == SPACE) p = "\\ "; else if (t == THIN) p = "\\|"; else if (t == TAB) p = "\\t"; else if ((tp = lookup(restbl, p1)) != NULL) { p = tp->cval; } else { lf = rf = 0; lastft = 0; nclass = NONE; /* get started with no class == no pad */ csp = cs; for (psp = p1; (c = textc()) != '\0'; ) { nextft = ft; pclass = nclass; rf = trans(c, p1); if (lf == 0) { lf = rf; /* left stuff is first found */ lclass[yyval] = nclass; } if (csp-cs > CSSIZE) ERROR "converted token %.25s... too long", p1 FATAL ; } sadd("\\fP"); *csp = '\0'; p = cs; lfont[yyval] = lf; rfont[yyval] = rf; rclass[yyval] = nclass; } dprintf(".\t%dtext: S%d <- %s; b=%g,h=%g,lf=%c,rf=%c,ps=%d\n", t, yyval, p, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval], ps); printf(".ds %d \"%s\n", yyval, p); }
/*make argv a whole string*/ char *argstr(int argc, char *argv[], int f) { char *str = malloc(slen(argv[f])); scp(argv[f], str); int i; for (i = f + 1; i < argc; i++) { str = realloc(str, slen(str) + slen(argv[i]) + 1); sadd(str, argv[i]); } return str; }
TEST test_spop() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; char *m1 = "mymember", *m2 = "member2"; sadd(context, "myset", m1); sadd(context, "myset", m2); rliteReply* reply; { char* argv[100] = {"spop", "myset", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); ASSERT_EQ(reply->type, RLITE_REPLY_STRING); if (!(reply->len == (int)strlen(m1) && memcmp(reply->str, m1, reply->len) == 0) && !(reply->len == (int)strlen(m2) && memcmp(reply->str, m2, reply->len) == 0)) { FAIL(); } rliteFreeReplyObject(reply); } { char* argv[100] = {"spop", "myset", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); ASSERT_EQ(reply->type, RLITE_REPLY_STRING); if (!(reply->len == (int)strlen(m1) && memcmp(reply->str, m1, reply->len) == 0) && !(reply->len == (int)strlen(m2) && memcmp(reply->str, m2, reply->len) == 0)) { FAIL(); } rliteFreeReplyObject(reply); } { char* argv[100] = {"spop", "myset", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_NIL(reply); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
TEST test_sunion() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; char *m1 = "mymember", *m2 = "member2", *s1 = "myset", *s2 = "myset2"; sadd(context, s1, m1); sadd(context, s1, m2); sadd(context, s2, m1); sadd(context, s2, "meh"); rliteReply* reply; { char* argv[100] = {"sunion", s1, s2, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 3); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
int main(void) { struct sint sum = { "0" }; FILE *fptr; fptr = fopen("./input-files/p013.txt", "r"); for (int i = 0; i < 100; i++) { struct sint in; fscanf(fptr, "%s", in.digits); sum = sadd(&sum, &in); } sum.digits[10] = '\0'; printf("%s\n", sum.digits); }
/* thread function */ void* threadfunc(void* arg) { long long iterations = (long long)arg; long long i; if (sync == 'm') { for (i = 0; i < iterations; i++) { madd(&counter, 1); } for (i = 0; i < iterations; i++) { madd(&counter, -1); } } else if (sync == 's') { for (i = 0; i < iterations; i++) { sadd(&counter, 1); } for (i = 0; i < iterations; i++) { sadd(&counter, -1); } } else if (sync == 'c') { for (i = 0; i < iterations; i++) { cadd(&counter, 1); } for (i = 0; i < iterations; i++) { cadd(&counter, -1); } } else { for (i = 0; i < iterations; i++) { add(&counter, 1); } for (i = 0; i < iterations; i++) { add(&counter, -1); } } }
TEST test_smove() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; sadd(context, "myset", "mymember"); rliteReply* reply; { char* argv[100] = {"smove", "myset", "otherset", "mymember", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"sismember", "myset", "mymember", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 0); rliteFreeReplyObject(reply); } { char* argv[100] = {"sismember", "otherset", "mymember", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"smove", "otherset", "myset", "member2", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 0); rliteFreeReplyObject(reply); } { char* argv[100] = {"sismember", "myset", "member2", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 0); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
void cAmp::PlsOpen() { OPENFILENAMEA ofn; ZeroMemory(&ofn,sizeof(ofn)); ofn.lStructSize = sizeof(ofn); char szFile[MP], sDir[MP]; ofn.hwndOwner = hWnd; ofn.lpstrFile = szFile; ofn.lpstrFile[0]='\0'; ofn.nMaxFile = sizeof(szFile); ofn.lpstrFilter = "cAmp Playlists (*.cp)\0*.cp\0"; ofn.nFilterIndex=1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; scpy(sDir, cSnd::appPath.c_str()); sadd(sDir, "playlists"); ofn.lpstrInitialDir = sDir; ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_ENABLESIZING| OFN_NOCHANGEDIR|OFN_NONETWORKBUTTON|OFN_HIDEREADONLY/*|OFN_ALLOWMULTISELECT*/; if (GetOpenFileNameA(&ofn)==TRUE) { char* pp = strrchr(ofn.lpstrFile,'\\')+1, *pe = strrchr(ofn.lpstrFile,'.'); pe[0]=0; //no dir,ext //dont duplicate pls names-- pls->name = /*ofn.lpstrFile*/pp; pls->Load(); } }
int main(void) { char in = 0; int digit = 0; struct sint current; struct sint max; max.digits[0]=0; struct sint min; for (int i=0; i<51; i++){ min.digits[i]='9'; } struct sint acc; acc.digits[0]=0; while (scanf("%c", &in)!=EOF){ if (in > '9' || in < '0'){ current.digits[digit] = 0; acc = sadd(¤t, &acc); if (scomp(¤t, &max)==1) { max = current; } if (scomp(&min, ¤t)==1) { min = current; } digit = 0; for (int i=0; i<51; i++){ current.digits[i]=0; } } else { current.digits[digit] = in; digit++; } } strim(&min); strim(&max); strim(&acc); printf("min:%s\n", min.digits); printf("max:%s\n", max.digits); printf("sum:%s\n", acc.digits); }
static int ncat_listen_stream(int proto) { int rc, i, fds_ready; fd_set listen_fds; /* clear out structs */ FD_ZERO(&master_readfds); FD_ZERO(&master_writefds); FD_ZERO(&master_broadcastfds); FD_ZERO(&listen_fds); #ifdef HAVE_OPENSSL FD_ZERO(&sslpending_fds); #endif zmem(&client_fdlist, sizeof(client_fdlist)); zmem(&broadcast_fdlist, sizeof(broadcast_fdlist)); #ifdef WIN32 set_pseudo_sigchld_handler(decrease_conn_count); #else /* Reap on SIGCHLD */ Signal(SIGCHLD, sigchld_handler); /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we send data to it before noticing. */ Signal(SIGPIPE, SIG_IGN); #endif #ifdef HAVE_OPENSSL if (o.ssl) setup_ssl_listen(); #endif /* We need a list of fds to keep current fdmax. The second parameter is a number added to the supplied connection limit, that will compensate maxfds for the added by default listen and stdin sockets. */ init_fdlist(&client_fdlist, sadd(o.conn_limit, num_listenaddrs + 1)); for (i = 0; i < NUM_LISTEN_ADDRS; i++) listen_socket[i] = -1; for (i = 0; i < num_listenaddrs; i++) { /* setup the main listening socket */ listen_socket[i] = do_listen(SOCK_STREAM, proto, &listenaddrs[i]); /* Make our listening socket non-blocking because there are timing issues * which could cause us to block on accept() even though select() says it's * readable. See UNPv1 2nd ed, p422 for more. */ unblock_socket(listen_socket[i]); /* setup select sets and max fd */ FD_SET(listen_socket[i], &master_readfds); add_fd(&client_fdlist, listen_socket[i]); FD_SET(listen_socket[i], &listen_fds); } add_fd(&client_fdlist, STDIN_FILENO); init_fdlist(&broadcast_fdlist, o.conn_limit); while (1) { /* We pass these temporary descriptor sets to fselect, since fselect modifies the sets it receives. */ fd_set readfds = master_readfds, writefds = master_writefds; struct fdinfo *fdi = NULL; if (o.debug > 1) logdebug("selecting, fdmax %d\n", client_fdlist.fdmax); if (o.debug > 1 && o.broker) logdebug("Broker connection count is %d\n", get_conn_count()); fds_ready = fselect(client_fdlist.fdmax + 1, &readfds, &writefds, NULL, NULL); if (o.debug > 1) logdebug("select returned %d fds ready\n", fds_ready); /* * FIXME: optimize this loop to look only at the fds in the fd list, * doing it this way means that if you have one descriptor that is very * large, say 500, and none close to it, that you'll loop many times for * nothing. */ for (i = 0; i <= client_fdlist.fdmax && fds_ready > 0; i++) { /* Loop through descriptors until there's something to read */ if (!FD_ISSET(i, &readfds) && !FD_ISSET(i, &writefds)) continue; if (o.debug > 1) logdebug("fd %d is ready\n", i); #ifdef HAVE_OPENSSL /* Is this an ssl socket pending a handshake? If so handle it. */ if (o.ssl && FD_ISSET(i, &sslpending_fds)) { FD_CLR(i, &master_readfds); FD_CLR(i, &master_writefds); fdi = get_fdinfo(&client_fdlist, i); switch(ssl_handshake(fdi)){ case NCAT_SSL_HANDSHAKE_COMPLETED: /* Clear from sslpending_fds once ssl is established */ FD_CLR(i, &sslpending_fds); rm_fd(&client_fdlist, i); post_handle_connection(*fdi); break; case NCAT_SSL_HANDSHAKE_PENDING_WRITE: FD_SET(i, &master_writefds); break; case NCAT_SSL_HANDSHAKE_PENDING_READ: FD_SET(i, &master_readfds); break; case NCAT_SSL_HANDSHAKE_FAILED: default: SSL_free(fdi->ssl); Close(fdi->fd); FD_CLR(i, &sslpending_fds); FD_CLR(i, &master_readfds); rm_fd(&client_fdlist, i); /* Are we in single listening mode(without -k)? If so then we should quit also. */ if (!o.keepopen && !o.broker) return 1; --conn_inc; break; } } else #endif if (FD_ISSET(i, &listen_fds)) { /* we have a new connection request */ handle_connection(i); } else if (i == STDIN_FILENO) { if(o.broker) { read_and_broadcast(i); }else { /* Read from stdin and write to all clients. */ rc = read_stdin(); if (rc == 0 && o.sendonly) /* There will be nothing more to send. If we're not receiving anything, we can quit here. */ return 0; if (rc < 0) return 1; } } else if (!o.sendonly) { if(o.broker) { read_and_broadcast(i); }else { /* Read from a client and write to stdout. */ rc = read_socket(i); if (rc <= 0 && !o.keepopen) return rc == 0 ? 0 : 1; } } fds_ready--; } } return 0; }
template <typename RET, typename LHS, typename RHS> constexpr Result<RET> mul(LHS &&lhs, RHS &&rhs) { RET sum{}; return {__builtin_mul_overflow(lhs, rhs, &sum), sum}; } static_assert(mul<int>(17,22) == Result<int>{false, 374}); static_assert(mul<int>(INT_MAX / 22, 23) == Result<int>{true, -2049870757}); static_assert(mul<int>(INT_MIN / 22, -23) == Result<int>{true, -2049870757}); constexpr Result<int> sadd(int lhs, int rhs) { int sum{}; return {__builtin_sadd_overflow(lhs, rhs, &sum), sum}; } static_assert(sadd(17,22) == Result<int>{false, 39}); static_assert(sadd(INT_MAX - 22, 23) == Result<int>{true, INT_MIN}); static_assert(sadd(INT_MIN + 22, -23) == Result<int>{true, INT_MAX}); constexpr Result<int> ssub(int lhs, int rhs) { int sum{}; return {__builtin_ssub_overflow(lhs, rhs, &sum), sum}; } static_assert(ssub(17,22) == Result<int>{false, -5}); static_assert(ssub(INT_MAX - 22, -23) == Result<int>{true, INT_MIN}); static_assert(ssub(INT_MIN + 22, 23) == Result<int>{true, INT_MAX}); constexpr Result<int> smul(int lhs, int rhs) { int sum{}; return {__builtin_smul_overflow(lhs, rhs, &sum), sum};
int trans(int c, char *) { int f; if (isalpharune(c) && ft == ITAL && c != 'f' && c != 'j') { /* italic letter */ shim(pclass, nclass = ILET); cadd(c); return ITAL; } if (isalpharune(c) && ft != ITAL) { /* other letter */ shim(pclass, nclass = OLET); cadd(c); return ROM; } if (isdigitrune(c)) { shim(pclass, nclass = DIG); roman(c); return ROM; /* this is the right side font of this object */ } f = ROM; nclass = OTHER; switch (c) { case ':': case ';': case '!': case '%': case '?': shim(pclass, nclass); roman(c); return f; case '(': case '[': shim(pclass, nclass = LPAR); roman(c); return f; case ')': case ']': shim(pclass, nclass = RPAR); roman(c); return f; case ',': shim(pclass, nclass = OTHER); roman(c); return f; case '.': if (rf == ROM) roman(c); else cadd(c); return f; case '|': /* postscript needs help with default width! */ shim(pclass, nclass = VBAR); sadd("\\v'.17m'\\z|\\v'-.17m'\\|"); /* and height */ return f; case '=': shim(pclass, nclass = PLUS); sadd("\\(eq"); return f; case '+': shim(pclass, nclass = PLUS); sadd("\\(pl"); return f; case '>': case '<': /* >, >=, >>, <, <-, <=, << */ shim(pclass, nclass = PLUS); if (*psp == '=') { sadd(c == '<' ? "\\(<=" : "\\(>="); psp++; } else if (c == '<' && *psp == '-') { /* <- only */ sadd("\\(<-"); psp++; } else if (*psp == c) { /* << or >> */ cadd(c); cadd(c); psp++; } else { cadd(c); } return f; case '-': shim(pclass, nclass = PLUS); /* probably too big for ->'s */ if (*psp == '>') { sadd("\\(->"); psp++; } else { sadd("\\(mi"); } return f; case '/': shim(pclass, nclass = SLASH); cadd('/'); return f; case '~': case ' ': sadd("\\|\\|"); return f; case '^': sadd("\\|"); return f; case '\\': /* troff - pass only \(xx without comment */ shim(pclass, nclass); cadd('\\'); cadd(c = *psp++); if (c == '(' && *psp && *(psp+1)) { cadd(*psp++); cadd(*psp++); } else fprintf(stderr, "eqn warning: unquoted troff command \\%c, file %s:%d\n", c, curfile->fname, curfile->lineno); return f; case '\'': shim(pclass, nclass); sadd("\\(fm"); return f; case 'f': if (ft == ITAL) { shim(pclass, nclass = ILETF); cadd('f'); f = ITAL; } else cadd('f'); return f; case 'j': if (ft == ITAL) { shim(pclass, nclass = ILETJ); cadd('j'); f = ITAL; } else cadd('j'); return f; default: shim(pclass, nclass); cadd(c); return ft==ITAL ? ITAL : ROM; } }
static int ncat_listen_stream(int proto) { int rc, i, fds_ready; fd_set listen_fds; struct timeval tv; struct timeval *tvp = NULL; unsigned int num_sockets; /* clear out structs */ FD_ZERO(&master_readfds); FD_ZERO(&master_writefds); FD_ZERO(&master_broadcastfds); FD_ZERO(&listen_fds); #ifdef HAVE_OPENSSL FD_ZERO(&sslpending_fds); #endif zmem(&client_fdlist, sizeof(client_fdlist)); zmem(&broadcast_fdlist, sizeof(broadcast_fdlist)); #ifdef WIN32 set_pseudo_sigchld_handler(decrease_conn_count); #else /* Reap on SIGCHLD */ Signal(SIGCHLD, sigchld_handler); /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we send data to it before noticing. */ Signal(SIGPIPE, SIG_IGN); #endif #ifdef HAVE_OPENSSL if (o.ssl) setup_ssl_listen(); #endif /* Not sure if this problem exists on Windows, but fcntl and /dev/null don't */ #ifndef WIN32 /* Check whether stdin is closed. Because we treat this fd specially, we * can't risk it being reopened for an incoming connection, so we'll hold * it open instead. */ if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF) { logdebug("stdin is closed, attempting to reserve STDIN_FILENO\n"); rc = open("/dev/null", O_RDONLY); if (rc >= 0 && rc != STDIN_FILENO) { /* Oh well, we tried */ logdebug("Couldn't reserve STDIN_FILENO\n"); close(rc); } } #endif /* We need a list of fds to keep current fdmax. The second parameter is a number added to the supplied connection limit, that will compensate maxfds for the added by default listen and stdin sockets. */ init_fdlist(&client_fdlist, sadd(o.conn_limit, num_listenaddrs + 1)); for (i = 0; i < NUM_LISTEN_ADDRS; i++) listen_socket[i] = -1; num_sockets = 0; for (i = 0; i < num_listenaddrs; i++) { /* setup the main listening socket */ listen_socket[num_sockets] = do_listen(SOCK_STREAM, proto, &listenaddrs[i]); if (listen_socket[num_sockets] == -1) { if (o.debug > 0) logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno())); continue; } /* Make our listening socket non-blocking because there are timing issues * which could cause us to block on accept() even though select() says it's * readable. See UNPv1 2nd ed, p422 for more. */ unblock_socket(listen_socket[num_sockets]); /* setup select sets and max fd */ FD_SET(listen_socket[num_sockets], &master_readfds); add_fd(&client_fdlist, listen_socket[num_sockets]); FD_SET(listen_socket[num_sockets], &listen_fds); num_sockets++; } if (num_sockets == 0) { if (num_listenaddrs == 1) bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno())); else bye("Unable to open any listening sockets."); } add_fd(&client_fdlist, STDIN_FILENO); init_fdlist(&broadcast_fdlist, o.conn_limit); if (o.idletimeout > 0) tvp = &tv; while (1) { /* We pass these temporary descriptor sets to fselect, since fselect modifies the sets it receives. */ fd_set readfds = master_readfds, writefds = master_writefds; struct fdinfo *fdi = NULL; if (o.debug > 1) logdebug("selecting, fdmax %d\n", client_fdlist.fdmax); if (o.debug > 1 && o.broker) logdebug("Broker connection count is %d\n", get_conn_count()); if (o.idletimeout > 0) ms_to_timeval(tvp, o.idletimeout); fds_ready = fselect(client_fdlist.fdmax + 1, &readfds, &writefds, NULL, tvp); if (o.debug > 1) logdebug("select returned %d fds ready\n", fds_ready); if (fds_ready == 0) bye("Idle timeout expired (%d ms).", o.idletimeout); /* * FIXME: optimize this loop to look only at the fds in the fd list, * doing it this way means that if you have one descriptor that is very * large, say 500, and none close to it, that you'll loop many times for * nothing. */ for (i = 0; i <= client_fdlist.fdmax && fds_ready > 0; i++) { /* Loop through descriptors until there's something to read */ if (!FD_ISSET(i, &readfds) && !FD_ISSET(i, &writefds)) continue; if (o.debug > 1) logdebug("fd %d is ready\n", i); #ifdef HAVE_OPENSSL /* Is this an ssl socket pending a handshake? If so handle it. */ if (o.ssl && FD_ISSET(i, &sslpending_fds)) { FD_CLR(i, &master_readfds); FD_CLR(i, &master_writefds); fdi = get_fdinfo(&client_fdlist, i); ncat_assert(fdi != NULL); switch (ssl_handshake(fdi)) { case NCAT_SSL_HANDSHAKE_COMPLETED: /* Clear from sslpending_fds once ssl is established */ FD_CLR(i, &sslpending_fds); post_handle_connection(*fdi); break; case NCAT_SSL_HANDSHAKE_PENDING_WRITE: FD_SET(i, &master_writefds); break; case NCAT_SSL_HANDSHAKE_PENDING_READ: FD_SET(i, &master_readfds); break; case NCAT_SSL_HANDSHAKE_FAILED: default: SSL_free(fdi->ssl); Close(fdi->fd); FD_CLR(i, &sslpending_fds); FD_CLR(i, &master_readfds); rm_fd(&client_fdlist, i); /* Are we in single listening mode(without -k)? If so then we should quit also. */ if (!o.keepopen && !o.broker) return 1; --conn_inc; break; } } else #endif if (FD_ISSET(i, &listen_fds)) { /* we have a new connection request */ handle_connection(i); } else if (i == STDIN_FILENO) { if (o.broker) { read_and_broadcast(i); } else { /* Read from stdin and write to all clients. */ rc = read_stdin(); if (rc == 0) { if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.sendonly)) { /* There will be nothing more to send. If we're not receiving anything, we can quit here. */ return 0; } if (!o.noshutdown) shutdown_sockets(SHUT_WR); } if (rc < 0) return 1; } } else if (!o.sendonly) { if (o.broker) { read_and_broadcast(i); } else { /* Read from a client and write to stdout. */ rc = read_socket(i); if (rc <= 0 && !o.keepopen) return rc == 0 ? 0 : 1; } } fds_ready--; } } return 0; }