THIS IS UNOFFICIAL, THERE ARE NO GUARANTEES FOR ANYTHING "" means "x" is optional "{a,b,c}" means one of a or b or c creat(2): int fd = creat(path, S_I{R,W,X}{USR,GRP,OTH} || S_IRWX{U,G,O}); // "||" denotes alternatives if (fd == -1) die(); scandir(3): struct dirent **namelist; int n = scandir(path, &namelist, filter, alphasort); if (n == -1) die(); for (int i = 0; i < n; i++) { // namelist[i]->d_name == name of entry work(namelist[i]); free(namelist[i]); } free(namelist); static int filter(const struct dirent *ent) { if (ent should be in namelist) return !0 } lstat(2): // info about link itself. stat(2) follows link struct stat info; if (lstat(path, &info)) { if (errno == ENOENT) { .. } else die(); // or just always die() } // info.st_size == size of file // S_IS{REG,DIR}(info.st_mode) for checking if it is a regular file/directory fcntl/dup2: int flags = fcntl(sock, F_GETFD, 0); if (fcntl(sock, F_SETFD, flags | FD_CLOEXEC)) die(); // duplicate fd + set close-on-exec int sockCopy = fcntl(sock, F_DUPFD_CLOEXEC, 0); if (sockCopy == -1) die(); if (dup2(old, new) == -1) die(); fork(2)/pthread_create(3): pid_t pid = fork(); if (pid == -1) die(); else if (pid == 0) child else parent pthread_t tid; if ((errno = pthread_create(&tid, NULL, twork, args)) != 0) die(); if ((errno = pthread_join(&tid, NULL)) != 0) perror(); static void *twork(void *args) { pthread_detach(pthread_self()); // only if not using pthread_join! // do work, probably in an endless loop return NULL; } exec(3): execlp(file, file <, arguments...>, NULL); execvp(file, argv); die(); qsort(3): qsort(data, counter, sizeof(data[0]), compare); static int compare(const void *a, const void *b) { return strcmp(*(char * *const) a, *(char * *const) b); // for strings } fgets(3): char buf[LENGTH + 1]; // +1 for '\0' if (!fgets(buf, sizeof(buf), rx)) { if (ferror(rx)) { // die or perror } // EOF } // do work string(3): // only "useful" functions str2 = strdup(str); if (!str2) die(); strtok(buf, "\n"); // in multithreaded programs, use strtok_r: char *saveptr; strtok_r(buf, "\n", &saveptr); char *s = strchr(str, 'a'); // s == first occurence of 'a' in str char *s = strstr(str, "abc"); // s == first occurence of substring "abc" in str strcmp(str1, str2); char *endptr; errno = 0; long val = strtol(str, &endptr, 10); if (errno) die(); if (str == endptr || *endptr != '\0') { // no digits || junk after digits } // if truncating to e.g. int, check for val > INT_MAX Client: const struct addrinfo hints = { .ai_socktype = SOCK_STREAM, .ai_family = AF_UNSPEC, .ai_flags = AI_ADDRCONFIG }; struct addrinfo *head; int tmp = getaddrinfo(address, "port", &hints, &head); if (tmp) { gai_strerror(tmp) + exit() } int s; struct addrinfo *cur; for (cur = head; cur; cur = cur->ai_next) { if ((s = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol)) == -1) continue; if (connect(s, cur->ai_addr, cur->ai_addrlen) == 0) break; close(s); } if (!cur) die(); freeaddrinfo(head); int s2 = dup(s); if (s2 == -1) die(); FILE *r = fdopen(s, "r"); FILE *w = fdopen(s2, "w"); if (!r || !w) die(); // do work fclose(r); fclose(w); Server: int ls = socket(AF_INET6, SOCK_STREAM, 0); if (ls == -1) die(); struct sockaddr_in6 name = { .sin6_family = AF_INET6, .sin6_port = htons(port), .sin6_addr = in6addr_any }; if (bind(ls, (struct sockaddr *) &name, sizeof(name)) != 0) die(); if (listen(ls, SOMAXCONN) != 0) die(); for (;;) { int cs; if ((cs = accept(ls, NULL, NULL)) == -1) continue; work(cs); } Signale (sigaction(2)/sigsetops(3)/sigprocmask(2)): struct sigaction new = { .sa_handler = {sigHandler,SIG_DFL,SIG_IGN}, .sa_flags = SA_RESTART // maybe SA_NOCLDWAIT }; sigemptyset(&new.sa_mask); struct sigaction old; // only if needed sigaction(SIGCHLD, &new, &old); static void sigHandler(int signum) { int errsv = errno; int status; int flags = WNOHANG; for (pid_t pid; (pid = waitpid(-1, &status, flags)) > 0; ) { .. } errno = errsv; } sigset_t set; sigemptyset(&set); sigfillset(&set); sigaddset(&set, SIGINT); sigdelset(&set, SIGUSR1); {sigprocmask,pthread_sigmask}({SIG_BLOCK,SIG_SETMASK}, &set, &oldset); Sync: _Atomic int value; do { expected = atomic_load(&value); new = expected + 123; } while (!atomic_compare_exchange_strong(&value, &expected, new)); pthread_mutex_t m; if ((errno = pthread_mutex_init(&m, NULL)) != 0) die(); pthread_cond_t c; if ((errno = pthread_cond_init(&c, NULL)) != 0) die(); pthread_mutex_lock(&m); // do work pthread_mutex_unlock(&m); pthread_cond_wait(&c, &m); pthread_cond_{broadcast,signal}(&c); pthread_mutex_destroy(&m); pthread_cond_destroy(&c);