util.c (2967B) download
1#include "util.h"
2
3#include <errno.h>
4#include <fcntl.h>
5#include <limits.h>
6#include <signal.h>
7#include <stdarg.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/stat.h>
12#include <unistd.h>
13
14
15ssize_t dgetline(int fd, char* line, size_t line_buffer) {
16 ssize_t line_size = 0;
17 ssize_t rc;
18 char c;
19
20 while (line_size < (ssize_t) line_buffer - 1 && (rc = read(fd, &c, 1)) == 1) {
21 if (c == '\r')
22 continue;
23 if (c == '\n')
24 break;
25 line[line_size++] = c;
26 }
27 line[line_size] = '\0';
28 if (rc == -1 && line_size == 0)
29 return -1;
30 return line_size;
31}
32
33ssize_t readstr(int fd, char* str) {
34 ssize_t len = 0;
35 int rc;
36
37 while ((rc = read(fd, &str[len], 1)) == 1 && str[len] != '\0')
38 len++;
39
40 str[len] = '\0';
41 return rc == -1 ? -1 : len;
42}
43
44ssize_t writestr(int fd, const char* str) {
45 if (str == NULL)
46 return write(fd, "", 1);
47 return write(fd, str, strlen(str) + 1);
48}
49
50unsigned int stat_mode(const char* format, ...) {
51 char path[PATH_MAX];
52 struct stat st;
53 va_list args;
54
55 va_start(args, format);
56 vsnprintf(path, PATH_MAX, format, args);
57 va_end(args);
58
59 if (stat(path, &st) == 0)
60 return st.st_mode;
61
62 return -1;
63}
64
65int fork_dup_cd_exec(int dir, const char* path, int fd0, int fd1, int fd2) {
66 pid_t pid;
67
68 if ((pid = fork()) == -1) {
69 fprint(1, "error: cannot fork process: %r\n");
70 return -1;
71 } else if (pid == 0) {
72 dup2(fd0, STDIN_FILENO);
73 dup2(fd1, STDOUT_FILENO);
74 dup2(fd2, STDERR_FILENO);
75
76 fchdir(dir);
77
78 execl(path, path, NULL);
79 fprint(1, "error: cannot execute stop process: %r\n");
80 _exit(1);
81 }
82 return pid;
83}
84
85int reclaim_console(void) {
86 int ttyfd;
87
88 if ((ttyfd = open("/dev/console", O_RDWR)) == -1)
89 return -1;
90
91 dup2(ttyfd, 0);
92 dup2(ttyfd, 1);
93 dup2(ttyfd, 2);
94 if (ttyfd > 2)
95 close(ttyfd);
96
97 return 0;
98}
99
100void sigblock_all(int unblock) {
101 sigset_t ss;
102
103 sigemptyset(&ss);
104 sigaddset(&ss, SIGALRM);
105 sigaddset(&ss, SIGCHLD);
106 sigaddset(&ss, SIGCONT);
107 sigaddset(&ss, SIGHUP);
108 sigaddset(&ss, SIGINT);
109 sigaddset(&ss, SIGPIPE);
110 sigaddset(&ss, SIGTERM);
111
112 sigprocmask(unblock, &ss, NULL);
113}
114
115
116long parse_long(const char* str, const char* name) {
117 char* end;
118 long l = strtol(str, &end, 10);
119
120 if (*end != '\0') {
121 fprint(1, "error: invalid %s '%s'\n", name, optarg);
122 exit(1);
123 }
124 return l;
125}
126
127char* progname(char* path) {
128 char* match;
129
130 for (;;) {
131 if ((match = strrchr(path, '/')) == NULL)
132 return path;
133
134 if (match[1] != '\0')
135 return match + 1;
136
137 *match = '\0';
138 }
139 return path;
140}
141
142int fd_set_flag(int fd, int flags) {
143 int rc;
144
145 if ((rc = fcntl(fd, F_GETFL)) == -1)
146 return -1;
147
148 rc |= flags;
149
150 if (fcntl(fd, F_SETFL, rc) == -1)
151 return -1;
152
153 return rc;
154}
155
156void path_join(char* buffer, const char* component, ...) {
157 va_list va;
158 int index = 0;
159
160 va_start(va, component);
161
162 do {
163 if (!index)
164 buffer[index++] = '/';
165 while (*component)
166 buffer[index++] = *(component++);
167 } while ((component = va_arg(va, const char*)));
168 buffer[index] = '\0';
169}