void dump_variants(int outfd, stringptr* section_name, variant_info_list* variants, stringptrlist* block_strings, size_t level, size_t previous_membercount, ssize_t backindent) { if(variants == NULL) return; variant_info* vp; stringptr* act, normalized; char norm_buf[1024]; size_t membercount; size_t* id; int switched = 0; sblist_iter(variants, vp) { membercount = sblist_getsize(vp->members); if(membercount == previous_membercount) { print_level_tabs(outfd, level - backindent); ulz_fprintf(outfd, "if(str[%zu]!='%c') goto main_default;\n", level, vp->c); backindent++; } else { if(!switched) { print_level_tabs(outfd, level - backindent); ulz_fprintf(outfd, "switch(str[%zu]) {\n", level); switched = 1; backindent--; } print_level_tabs(outfd, level - backindent); ulz_fprintf(outfd, "case '%c':\n", vp->c); } if(!vp->variants) { print_level_tabs(outfd, level - backindent); id = sblist_get(vp->members, 0); act = sblist_get(block_strings, *id); normalized = normalize(act, norm_buf, sizeof(norm_buf)); log_put(outfd, VARISL("\treturn stringswitch_enumerator_member_name("), VARIS(section_name), VARISL(", "), VARIS(&normalized), VARISL(");"), NULL); } dump_variants(outfd, section_name, vp->variants, block_strings, level+1, membercount, backindent); }
void launch_thread(jobtype ptype, pkgstate* state, pkg_exec* item, pkgdata* data) { char* arr[2]; create_script(ptype, state, item, data); log_timestamp(1); log_putspace(1); if(ptype == JT_DOWNLOAD) { log_puts(1, SPL("downloading ")); } else log_puts(1, SPL("building ")); log_put(1, VARIS(item->name), VARISL("("), VARIS(item->scripts.filename), VARISL(") -> "), VARIS(item->scripts.stdoutfn), NULL); arr[0] = item->scripts.filename->ptr; arr[1] = NULL; posix_spawn_file_actions_init(&item->fa); posix_spawn_file_actions_addclose(&item->fa, 0); posix_spawn_file_actions_addclose(&item->fa, 1); posix_spawn_file_actions_addclose(&item->fa, 2); posix_spawn_file_actions_addopen(&item->fa, 0, "/dev/null", O_RDONLY, 0); posix_spawn_file_actions_addopen(&item->fa, 1, item->scripts.stdoutfn->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); posix_spawn_file_actions_adddup2(&item->fa, 1, 2); int ret = posix_spawnp(&item->pid, arr[0], &item->fa, NULL, arr, environ); if(ret == -1) { log_perror("posix_spawn"); die(SPL("")); } }
void write_enum(int outfd, sectionrec* sref) { hashlist* h; hashlist_iterator iter2; hashrec *href; stringptrlist* newlist; size_t i; stringptr *entry, normalized; char norm_buf[1024]; char buf[1024]; log_put(outfd, VARISL("typedef enum {\n\tstringswitch_enumerator_default_member_name("), VARIS(sref->id), VARISL("),"), NULL); h = sref->h; hashlist_iterator_init(&iter2); while((href = hashlist_next(h, &iter2))) { newlist = href->list; for(i = 0; i < stringptrlist_getsize(newlist); i++) { entry = stringptrlist_get(newlist, i); log_put(1, VARISL("id "), VARIS(sref->id), VARISL(", entry: "), VARII((int) entry->size), VARISL(", "), VARIS(entry), NULL); normalized = normalize(entry, norm_buf, sizeof(norm_buf)); ulz_snprintf(buf, sizeof(buf), "\tstringswitch_enumerator_member_name(%s, %s),\n", sref->id->ptr, normalized.ptr); log_putc(outfd, buf); } } log_put(outfd, VARISL("} stringswitch_enumerator_name("), VARIS(sref->id), VARISL(");\n"), NULL); }
void print_queue(pkgstate* state, jobtype jt) { sblist* queue = (jt == JT_DOWNLOAD) ? state->dl_queue : state->build_queue; char *queuename = (jt == JT_DOWNLOAD) ? "download" : "build"; pkg_exec* listitem; log_put(1, VARISL("*** "), VARIC(queuename), VARISL("queue ***"), NULL); sblist_iter(queue, listitem) { log_puts(1, listitem->name); log_putln(1); }
// forced == 1 static void socksserver_disconnect_client(socksserver* srv, int fd, int forced) { fdinfo* client = &srv->clients[fdindex(fd)]; int fdflag = 0; if(CONFIG_LOG && srv->log) { logstart(); printfd(fd); LOGPUT(1, VARISL(" disconnect, forced: "), VARII(forced), NULL); } if(forced) rocksockserver_disconnect_client(&srv->serva, fd); client->state = SS_DISCONNECTED; if(client->data) { client->data->state = BS_UNUSED; client->data->start = 0; client->data->used = 0; } if(client->target_fd != -1) fdflag = 1; fd = client->target_fd; client->target_fd = -1; if(fdflag) { srv->clients[fdindex(fd)].target_fd = -1; socksserver_disconnect_client(srv, fd, 1); } }
//return 0 on success. //checks if filesize and/or sha512 matches, if used. int verify_tarball(pkgconfig* cfg, pkgdata* package) { char buf[4096]; char* error; SHA512_CTX ctx; int fd; uint64_t pos, len = 0, nread; stringptr hash; get_tarball_filename_with_path(cfg, package, buf, sizeof(buf)); if(package->filesize) { len = getfilesize(buf); if(len < package->filesize) { log_put(2, VARISL("WARNING: "), VARIC(buf), VARISL(" filesize too small!"), NULL); return 1; } else if (len > package->filesize) { log_put(2, VARISL("WARNING: "), VARIC(buf), VARISL(" filesize too big!"), NULL); return 2; } } if(package->sha512) { if(!len) len = getfilesize(buf); fd = open(buf, O_RDONLY); if(fd == -1) { error = strerror(errno); log_put(2, VARISL("WARNING: "), VARIC(buf), VARISL(" failed to open: "), VARIC(error), NULL); return 3; } SHA512_Init(&ctx); pos = 0; while(pos < len) { nread = read(fd, buf, sizeof(buf)); SHA512_Update(&ctx, (const uint8_t*) buf, nread); pos += nread; } close(fd); SHA512_End(&ctx, (char*) buf); hash.ptr = buf; hash.size = strlen(buf); if(!EQ(&hash, package->sha512)) { log_put(2, VARISL("WARNING: "), VARIS(package->name), VARISL(" sha512 mismatch, got "), VARIS(&hash), VARISL(", expected "), VARIS(package->sha512), NULL); return 4; } } return 0; }
void fill_slots(jobtype ptype, pkgstate* state) { size_t i; pkg_exec* item; pkgdata* pkg; int* slots = (ptype == JT_DOWNLOAD) ? &state->slots.dl_slots : &state->slots.build_slots; sblist* queue = (ptype == JT_DOWNLOAD) ? state->dl_queue : state->build_queue; for(i = 0; *slots && i < sblist_getsize(queue); i++) { item = sblist_get(queue, i); if(item->pid == -1) { pkg = packagelist_get(state->package_list, item->name, stringptr_hash(item->name)); if(ptype == JT_DOWNLOAD || has_all_deps(state, pkg)) { if(ptype == JT_BUILD && !pkg->verified) { if (! (pkg->verified = !(verify_tarball(&state->cfg, pkg)))) { log_put(2, VARISL("WARNING: "), VARIS(item->name), VARISL(" failed to verify! please delete its tarball and retry downloading it."), NULL); continue; } } launch_thread(ptype, state, item, pkg); (*slots)--; } } } }
static int socksserver_on_clientconnect (void* userdata, struct sockaddr_storage* clientaddr, int fd) { socksserver* srv = (socksserver*) userdata; char buffer[256]; (void) buffer; if(CONFIG_LOG && srv->log && clientaddr) { logstart(); printfd(fd); LOGPUT(1, VARISL(" connect from: "), VARIC(get_client_ip(clientaddr, buffer, sizeof(buffer))), NULL); } if(fd < 3 || fd >= MAX_FD) { rocksockserver_disconnect_client(&srv->serva, fd); return -2; } fdinfo* client = &srv->clients[fdindex(fd)]; // put into nonblocking mode, so that writes will not block the server int flags = fcntl(fd, F_GETFL); if(flags == -1) return -1; if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) return -2; client->data = find_free_buffer(srv); if (!client->data) { if(CONFIG_LOG && srv->log) { logstart(); LOGPUTS(1, SPL("warning: couldnt find free buffer\n")); } rocksockserver_disconnect_client(&srv->serva, fd); return -2; } client->state = SS_CONNECTED; client->data->state = BS_IDLE; client->data->start = 0; client->target_fd = -1; return 0; }
static int socksserver_connect_request(socksserver* srv, int fd) { fdinfo* client = &srv->clients[fdindex(fd)]; size_t i = 0; unsigned char dlen = 0; unsigned char* buf = client->data->buf; int flags, ret; host_info addr; struct addrinfo addrbuf; struct sockaddr sockbuf; memset(&addr, 0, sizeof(addr)); memset(&addrbuf, 0, sizeof(addrbuf)); memset(&sockbuf, 0, sizeof(sockbuf)); addrbuf.ai_addr = &sockbuf; addr.hostaddr = &addrbuf; if(!client->data->start) return -1; if(buf[i++] != 5) return EC_NOT_ALLOWED; // check first byte whenever the message length is > 0 to not waste resources on maldoers if(client->data->start < 1+1+1+1+4+2) return -1; if(buf[i++] != 1) return EC_COMMAND_NOT_SUPPORTED; // we support only the connect method. if(buf[i++] != 0) return EC_GENERAL_FAILURE; switch(buf[i++]) { case 1: //ipv4 memcpy(&((struct sockaddr_in*) addr.hostaddr->ai_addr)->sin_addr, buf + 4, 4); memcpy(&((struct sockaddr_in*) addr.hostaddr->ai_addr)->sin_port, buf + 8, 2); ((struct sockaddr_in*) addr.hostaddr->ai_addr)->sin_family = PF_INET; addr.hostaddr->ai_addr->sa_family = PF_INET; addr.hostaddr->ai_addrlen = sizeof(struct sockaddr_in); break; case 3: //dns if(CONFIG_DNS) { dlen = buf[i++]; if(client->data->start < 1U+1U+1U+1U+1U+dlen+2U) return -1; addr.port = my_ntohs(buf + i + dlen); buf[i + dlen] = 0; addr.host = (char*) (buf + i); if(CONFIG_IPV6) addr.hostaddr = NULL; if(!resolve_host(&addr)) { if(CONFIG_IPV6) { memcpy(&addrbuf, addr.hostaddr, sizeof(struct addrinfo)); freeaddrinfo(addr.hostaddr); addr.hostaddr = &addrbuf; } } else goto notsupported; break; } else goto notsupported; case 4: //ipv6 if(CONFIG_IPV6) { if(client->data->start < 1+1+1+1+16+2) return -1; memcpy(&((struct sockaddr_in6*) addr.hostaddr->ai_addr)->sin6_addr, buf + 4, 16); memcpy(&((struct sockaddr_in6*) addr.hostaddr->ai_addr)->sin6_port, buf + 20, 2); ((struct sockaddr_in6*) addr.hostaddr->ai_addr)->sin6_family = PF_INET6; addr.hostaddr->ai_addr->sa_family = PF_INET6; addr.hostaddr->ai_addrlen = sizeof(struct sockaddr_in6); break; } default: notsupported: return EC_ADDRESSTYPE_NOT_SUPPORTED; } client->target_fd = socket(addr.hostaddr->ai_addr->sa_family, SOCK_STREAM, 0); if(client->target_fd == -1) { neterror: switch(errno) { case ENETDOWN: case ENETUNREACH: case ENETRESET: return EC_NET_UNREACHABLE; case EHOSTUNREACH: case EHOSTDOWN: return EC_HOST_UNREACHABLE; case ECONNREFUSED: return EC_CONN_REFUSED; default: return EC_GENERAL_FAILURE; } } if(client->target_fd >= MAX_FD) { close(client->target_fd); return EC_GENERAL_FAILURE; } flags = fcntl(client->target_fd, F_GETFL); if(flags == -1) return EC_GENERAL_FAILURE; if(fcntl(client->target_fd, F_SETFL, flags | O_NONBLOCK) == -1) return EC_GENERAL_FAILURE; ret = connect(client->target_fd, addr.hostaddr->ai_addr, addr.hostaddr->ai_addrlen); if(ret == -1) { ret = errno; if (!(ret == EINPROGRESS || ret == EWOULDBLOCK)) goto neterror; } srv->clients[fdindex(client->target_fd)].state = SS_SOCKSTARGET; srv->clients[fdindex(client->target_fd)].data = client->data; srv->clients[fdindex(client->target_fd)].target_fd = fd; rocksockserver_watch_fd(&srv->serva, client->target_fd); if(CONFIG_LOG && srv->log) { if(get_client_ip((struct sockaddr_storage*) addr.hostaddr->ai_addr, (char*) buf, CLIENT_BUFSIZE)) { logstart(); printfd(fd); LOGPUTS(1, SPLITERAL(" -> ")); printfd(client->target_fd); LOGPUT(1, VARISL(" <"), VARIC((char*)buf), VARISL(">"), NULL); } } return EC_SUCCESS; }