protocols/
test/
.clang-format
571 B
.clangd
365 B
.gitignore
82 B
.gitsigners
91 B
LICENSE
32.3 KiB
LICENSE.dwl
34.9 KiB
LICENSE.dwm
2.0 KiB
LICENSE.spectrwm
1.3 KiB
LICENSE.sway
1.0 KiB
LICENSE.tinywl
7.0 KiB
Makefile
7.8 KiB
PKGBUILD
952 B
README
5.6 KiB
config.def.h
15.7 KiB
config.mk
269 B
swm.1.adoc
3.3 KiB
swm.c
246.5 KiB
swm.desktop
81 B
swm.h
3.5 KiB
swmctl.1.adoc
2.5 KiB
swmctl.c
19.6 KiB
util.c
2.2 KiB
util.h
399 B
util.c
raw
| 1 | #include <fcntl.h> |
| 2 | #include <stdarg.h> |
| 3 | #include <stdio.h> |
| 4 | #include <stdlib.h> |
| 5 | #include <string.h> |
| 6 | |
| 7 | #include "util.h" |
| 8 | |
| 9 | #define MAX_ENV_SIZE 1024 |
| 10 | |
| 11 | /* Print an error and terminate the process. */ |
| 12 | [[noreturn]] void die(const char *fmt, ...) { |
| 13 | va_list ap; |
| 14 | |
| 15 | fputs("swm: ", stderr); |
| 16 | va_start(ap, fmt); |
| 17 | vfprintf(stderr, fmt, ap); |
| 18 | va_end(ap); |
| 19 | |
| 20 | if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { |
| 21 | fputc(' ', stderr); |
| 22 | perror(nullptr); |
| 23 | } else { |
| 24 | fputc('\n', stderr); |
| 25 | } |
| 26 | exit(1); |
| 27 | } |
| 28 | |
| 29 | /* Expand environment variables while preserving a single argv element. */ |
| 30 | size_t env_expand(char *output, size_t capacity, const char *input) { |
| 31 | const char *value; |
| 32 | size_t i = 0, len, out = 0, start; |
| 33 | char name[MAX_ENV_SIZE]; |
| 34 | |
| 35 | if (!capacity) |
| 36 | return 0; |
| 37 | |
| 38 | while (input[i]) { |
| 39 | if (input[i] != '$') { |
| 40 | if (out + 1 >= capacity) |
| 41 | return 0; |
| 42 | output[out++] = input[i]; |
| 43 | i++; |
| 44 | continue; |
| 45 | } |
| 46 | start = ++i; |
| 47 | if (!((input[i] >= 'A' && input[i] <= 'Z') || (input[i] >= 'a' && input[i] <= 'z') || |
| 48 | input[i] == '_')) { |
| 49 | if (out + 1 >= capacity) |
| 50 | return 0; |
| 51 | output[out++] = '$'; |
| 52 | continue; |
| 53 | } |
| 54 | for (; (input[i] >= 'A' && input[i] <= 'Z') || (input[i] >= 'a' && input[i] <= 'z') || |
| 55 | (input[i] >= '0' && input[i] <= '9') || input[i] == '_'; |
| 56 | i++) |
| 57 | ; |
| 58 | |
| 59 | len = i - start; |
| 60 | if (len >= sizeof(name)) |
| 61 | return 0; |
| 62 | memcpy(name, input + start, len); |
| 63 | name[len] = '\0'; |
| 64 | value = getenv(name); |
| 65 | if (!value) |
| 66 | continue; |
| 67 | |
| 68 | len = strlen(value); |
| 69 | if (out + len >= capacity) |
| 70 | return 0; |
| 71 | memcpy(output + out, value, len); |
| 72 | out += len; |
| 73 | } |
| 74 | output[out] = '\0'; |
| 75 | |
| 76 | return out + 1; |
| 77 | } |
| 78 | |
| 79 | /* Put a file descriptor into nonblocking mode. */ |
| 80 | int fd_set_nonblock(int fd) { |
| 81 | int flags = fcntl(fd, F_GETFL); |
| 82 | |
| 83 | if (flags < 0) { |
| 84 | perror("fcntl(F_GETFL)"); |
| 85 | return -1; |
| 86 | } |
| 87 | if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { |
| 88 | perror("fcntl(F_SETFL)"); |
| 89 | return -1; |
| 90 | } |
| 91 | return 0; |
| 92 | } |