-
Notifications
You must be signed in to change notification settings - Fork 9
/
lklib.c
195 lines (177 loc) · 4.36 KB
/
lklib.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include "lklib.h"
// forward declarations
void close_pipes(int pair1[2], int pair2[2], int pair3[2]);
// Print the last error message corresponding to errno.
void lk_print_err(char *s) {
fprintf(stderr, "%s: %s\n", s, strerror(errno));
}
void lk_exit_err(char *s) {
lk_print_err(s);
exit(1);
}
// Return whether line is empty, ignoring whitespace chars ' ', \r, \n
int is_empty_line(char *s) {
int slen = strlen(s);
for (int i=0; i < slen; i++) {
// Not an empty line if non-whitespace char is present.
if (s[i] != ' ' && s[i] != '\n' && s[i] != '\r') {
return 0;
}
}
return 1;
}
// Return whether string ends with \n char.
int ends_with_newline(char *s) {
int slen = strlen(s);
if (slen == 0) {
return 0;
}
if (s[slen-1] == '\n') {
return 1;
}
return 0;
}
// Like popen() but returning input, output, error fds for cmd.
int lk_popen3(char *cmd, int *fd_in, int *fd_out, int *fd_err) {
int z;
int in[2] = {0, 0};
int out[2] = {0, 0};
int err[2] = {0, 0};
z = pipe(in);
if (z == -1) {
return z;
}
z = pipe(out);
if (z == -1) {
close_pipes(in, out, err);
return z;
}
z = pipe(err);
if (z == -1) {
close_pipes(in, out, err);
return z;
}
int pid = fork();
if (pid == 0) {
// child proc
z = dup2(in[0], STDIN_FILENO);
if (z == -1) {
close_pipes(in, out, err);
return z;
}
z = dup2(out[1], STDOUT_FILENO);
if (z == -1) {
close_pipes(in, out, err);
return z;
}
// If fd_err parameter provided, use separate fd for stderr.
// If fd_err is NULL, combine stdout and stderr into fd_out.
if (fd_err != NULL) {
z = dup2(err[1], STDERR_FILENO);
if (z == -1) {
close_pipes(in, out, err);
return z;
}
} else {
z = dup2(out[1], STDERR_FILENO);
if (z == -1) {
close_pipes(in, out, err);
return z;
}
}
close_pipes(in, out, err);
z = execl("/bin/sh", "sh", "-c", cmd, NULL);
return z;
}
// parent proc
if (fd_in != NULL) {
*fd_in = in[1]; // return the other end of the dup2() pipe
}
close(in[0]);
if (fd_out != NULL) {
*fd_out = out[0];
}
close(out[1]);
if (fd_err != NULL) {
*fd_err = err[0];
}
close(err[1]);
return 0;
}
void close_pipes(int pair1[2], int pair2[2], int pair3[2]) {
int z;
int tmp_errno = errno;
if (pair1[0] != 0) {
z = close(pair1[0]);
if (z == 0) {
pair1[0] = 0;
}
}
if (pair1[1] != 0) {
z = close(pair1[1]);
if (z == 0) {
pair1[1] = 0;
}
}
if (pair2[0] != 0) {
z = close(pair2[0]);
if (z == 0) {
pair2[0] = 0;
}
}
if (pair2[1] != 0) {
z = close(pair2[1]);
if (z == 0) {
pair2[1] = 0;
}
}
if (pair3[0] != 0) {
z = close(pair3[0]);
if (z == 0) {
pair3[0] = 0;
}
}
if (pair3[1] != 0) {
z = close(pair3[1]);
if (z == 0) {
pair3[1] = 0;
}
}
errno = tmp_errno;
return;
}
void get_localtime_string(char *time_str, size_t time_str_len) {
time_t t = time(NULL);
struct tm tmtime;
void *pz = localtime_r(&t, &tmtime);
if (pz != NULL) {
int z = strftime(time_str, time_str_len, "%d/%b/%Y %H:%M:%S", &tmtime);
if (z == 0) {
sprintf(time_str, "???");
}
} else {
sprintf(time_str, "???");
}
}
// Return matching item in lookup table given testk.
// tbl is a null-terminated array of char* key-value pairs
// Ex. tbl = {"key1", "val1", "key2", "val2", "key3", "val3", NULL};
// where key1/val1, key2/val2, key3/val3 are the key-value pairs.
void **lk_lookup(void **tbl, char *testk) {
void **p = tbl;
while (*p != NULL) {
char *k = *p;
if (k == NULL) break;
if (!strcmp(k, testk)) {
return *(p+1); // val
}
p += 2; // next key
}
return NULL;
}