#include #include #include #include #include #include #include "utils.h" #include "minecctl.h" bool use_colors = false; /* FIXME: Can be shared */ void set_use_colors() { int fd; const char *e; if (getenv("NO_COLOR")) return; fd = fileno(stderr); if (fd < 0) return; if (!isatty(fd)) return; e = getenv("TERM"); if (!e) return; if (streq(e, "dumb")) return; use_colors = true; } char * strv_join(char * const *strv) { size_t len = 0; char *r, *to; for (unsigned i = 0; strv[i]; i++) len += strlen(strv[i]) + 1; if (len == 0) return NULL; r = zmalloc(len); to = r; for (unsigned i = 0; strv[i]; i++) { if (i > 0) *(to++) = ' '; to = stpcpy(to, strv[i]); } return r; } char * ask_password() { struct termios old, new; char *password = NULL; size_t len = 0; ssize_t r; if (!isatty(STDIN_FILENO)) return NULL; if (tcgetattr(STDIN_FILENO, &old) < 0) return NULL; new = old; new.c_lflag &= ~ECHO; new.c_lflag |= ICANON; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new) < 0) return NULL; fprintf(stderr, "Password: "); r = getline(&password, &len, stdin); tcsetattr(STDIN_FILENO, TCSAFLUSH, &old); if (r < 0) { info("Error in getline: %m"); clearerr(stdin); free(password); return NULL; } while (r > 0 && password[r - 1] == '\n') password[--r] = '\0'; return password; } int connect_any(struct list_head *addrs, bool may_fail) { struct saddr *saddr; bool connected = false; int sfd; if (list_empty(addrs)) die("No address to connect to"); list_for_each_entry(saddr, addrs, list) { verbose("Attempting connection to %s", saddr->addrstr); sfd = socket(saddr->storage.ss_family, SOCK_STREAM | SOCK_CLOEXEC, 0); if (sfd < 0) die("socket: %m"); socket_set_low_latency(sfd, true, true, true); if (connect(sfd, (struct sockaddr *)&saddr->storage, saddr->addrlen) < 0) { close(sfd); continue; } connected = true; break; } if (!connected && may_fail) return -1; else if (!connected) die("Failed to connect to remote host"); return sfd; } void __debug(_unused_ enum debug_lvl lvl, const char *fmt, ...) { va_list ap; if (use_colors) { if (lvl & DBG_ERROR) fprintf(stderr, ANSI_RED); else if (!(lvl & (DBG_INFO | DBG_VERBOSE))) fprintf(stderr, ANSI_GREY); } va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if (use_colors && !(lvl & (DBG_INFO | DBG_VERBOSE))) fprintf(stderr, ANSI_NORMAL); } _noreturn_ void __die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); exit(EXIT_FAILURE); } void * __zmalloc(const char *fn, int line, size_t size) { void *ptr; assert_die(!empty_str(fn) && line > 0 && size > 0, "invalid arguments"); ptr = calloc(1, size); if (!ptr) die("malloc: %m"); return ptr; } char * __xstrdup(const char *fn, int line, const char *s) { char *ptr; assert_die(!empty_str(fn) && line > 0 && !empty_str(s), "invalid arguments"); ptr = strdup(s); if (!ptr) die("strdup: %m"); return ptr; } char * __xstrndup(const char *fn, int line, const char *s, size_t n) { char *ptr; assert_die(!empty_str(fn) && line > 0 && !empty_str(s) && n > 0, "invalid arguments"); ptr = strndup(s, n); if (ptr) die("strdup: %m"); return ptr; } void __xfree(const char *fn, int line, void *ptr) { assert_die(!empty_str(fn) && line > 0, "invalid arguments"); free(ptr); }