/*------------------------------------------------ add commands to MENUSTRUCT and HMENU --------------------------------------------------*/ int ReadMenuCommands(HMENU hmenu, const char *p, MENUSTRUCT* pmenus) { int count = 0; int idCommand = 1; char name[81], command[MAX_PATH]; while(*p) { if(*p == '#' || *p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') { p = nextline(p); } else if(*p == '-' && *(p + 1) == '-') { if(hmenu) AppendMenu(hmenu, MF_SEPARATOR, 0, 0); p = nextline(p); } else { BOOL bdigit; int id, i; char quot; quot = 0; if(*p == '\"' || *p == '\'') { quot = *p; p++; } for(i = 0; i < 80 && *p && *p != '\r' && *p != '\n'; i++) { if(quot) { if(*p == quot) { p++; break; } } else if(*p == ' ' || *p == '\t') break; name[i] = *p++; } name[i] = 0; while(*p == ' ' || *p == '\t') p++; quot = 0; if(*p == '\"' || *p == '\'') { quot = *p; p++; } for(i = 0; i < MAX_PATH-1 && *p && *p != '\r' && *p != '\n'; i++) { if(quot && *p == quot) break; command[i] = *p++; } command[i] = 0; bdigit = isdigitstr(command); if(bdigit) id = atoi(command); else id = idCommand; if(hmenu) AppendMenu(hmenu, MF_STRING, id, name); if(!bdigit) { if(pmenus) { pmenus[count].id = id; strcpy(pmenus[count].command, command); } count++; if(count >= 50) return count; idCommand++; } p = nextline(p); } } return count; }
int addr_mksocket(const char *host, const char *service, int socktype, int aflags, conbind_t func, struct sockaddr *sockaddr, size_t *addrlen, int64_t softto_us, int64_t hardto_us) { D("invoked: host='%s', serv='%s', scktype: %d, aflags: %d, func: %s, sto=%lu, hto=%lu", host, service, socktype, aflags, !func ? "(none)" : func == connect ? "connect" : func == bind ? "bind" : "(unkonwn)", softto_us, hardto_us); struct addrinfo *ai_list = NULL; struct addrinfo hints; int64_t hardtsend = hardto_us ? tstamp_us() + hardto_us : 0; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = socktype; hints.ai_protocol = 0; hints.ai_flags = aflags; if (isdigitstr(service)) hints.ai_flags |= AI_NUMERICSERV; D("calling getaddrinfo on '%s:%s'", host, service); int r = getaddrinfo(host, service, &hints, &ai_list); if (r != 0) { W("getaddrinfo() failed: %s", gai_strerror(r)); return -1; } if (!ai_list) { W("getaddrinfo() result address list empty"); return -1; } bool success = false; int sck = -1; D("iterating over result list..."); for (struct addrinfo *ai = ai_list; ai; ai = ai->ai_next) { sck = -1; if (hardtsend && hardtsend - tstamp_us() <= 0) { W("hard timeout"); return 0; } D("next result, creating socket (fam=%d, styp=%d, prot=%d)", ai->ai_family, ai->ai_socktype, ai->ai_protocol); sck = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sck < 0) { WE("cannot create socket"); continue; } char peeraddr[64] = "(non-INET/INET6)"; unsigned short peerport = 0; if (ai->ai_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in*)ai->ai_addr; inet_ntop(AF_INET, &sin->sin_addr, peeraddr, sizeof peeraddr); peerport = ntohs(sin->sin_port); } else if (ai->ai_family == AF_INET6) { struct sockaddr_in6 *sin = (struct sockaddr_in6*)ai->ai_addr; inet_ntop(AF_INET6, &sin->sin6_addr, peeraddr, sizeof peeraddr); peerport = ntohs(sin->sin6_port); } char portstr[7]; snprintf(portstr, sizeof portstr, ":%hu", peerport); strNcat(peeraddr, portstr, sizeof peeraddr); int opt = 1; socklen_t optlen = sizeof opt; D("peer addr is '%s'", peeraddr); if (sockaddr) *sockaddr = *(ai->ai_addr); if (addrlen) *addrlen = ai->ai_addrlen; if (func) { D("going non-blocking"); if (setblocking(sck, false) == -1) { WE("failed to enable nonblocking mode"); close(sck); continue; } D("set to nonblocking mode, calling the backend function..."); errno = 0; bool doselect = false; int r = func(sck, ai->ai_addr, ai->ai_addrlen); if (r == -1 && (errno != EINPROGRESS)) { WE("backend failed"); close(sck); continue; } else if (r == -1) doselect = true; int64_t trem = 0; D("backend returned with %d", r); if (doselect) { if (hardtsend) { trem = hardtsend - tstamp_us(); if (trem <= 0) { D("hard timeout detected"); close(sck); continue; } } int64_t softtsend = softto_us ? tstamp_us() + softto_us : 0; if (softtsend) { int64_t trem_tmp = softtsend - tstamp_us(); if (trem_tmp <= 0) { W("soft timeout"); close(sck); continue; } if (trem_tmp < trem) trem = trem_tmp; } D("calling io_select1w (timeout: %lld us)", trem); r = io_select1w(sck, trem, true); if (r < 0) { WE("select() failed"); close(sck); continue; } else if (!r) { W("select() timeout"); close(sck); continue; } else D("selected!"); D("calling getsockopt to query error state"); if (getsockopt(sck, SOL_SOCKET, SO_ERROR, &opt, &optlen) != 0) { W("getsockopt failed"); close(sck); continue; } if (opt == 0) { I("socket in good shape! ('%s')", peeraddr); if (setblocking(sck, true) == -1) { WE("failed to disable nonblocking mode"); close(sck); continue; } success = true; break; } else { char errstr[256]; strerror_r(opt, errstr, sizeof errstr); W("backend function failed (%d: %s)", opt, errstr); close(sck); continue; } } else { I("There we go... ('%s')", peeraddr); if (setblocking(sck, true) == -1) { WE("failed to disable nonblocking mode"); close(sck); continue; } success = true; break; } } else { success = true; break; } } D("after loop; alling freeaddrinfo then returning %d", sck); freeaddrinfo(ai_list); return success ? sck : -1; }