22#include <sys/socket.h>
32 for (
const char *p = str; *p; p++) {
44 clock_gettime(CLOCK_MONOTONIC, &ts);
45 return (
double) ts.tv_sec + (double) ts.tv_nsec * 1.0e-9;
52 struct sockaddr_un addr;
53 addr.sun_family = AF_UNIX;
56 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
57 fprintf(stderr,
"socket() failed: %s\n", strerror(errno));
61 char *
path = addr.sun_path;
62 int len = (int)
sizeof(addr.sun_path);
63 if (snprintf(
path, len,
"%s/.dillo/ctl/%s",
dGethomedir(), pid) >= len) {
64 fprintf(stderr,
"pid path too long\n");
69 double maxtime = t0 + 10.0;
70 double warntime = t0 + 1.0;
72 struct timespec dur = { .tv_sec = 0, .tv_nsec = 50UL * 1000UL * 1000UL };
75 if (connect(fd, (
struct sockaddr *) &addr,
sizeof(addr)) == 0) {
78 }
else if (errno != ENOENT) {
79 fprintf(stderr,
"connect to %s failed: %s\n",
path, strerror(errno));
84 fprintf(stderr,
"connect to %s taking long\n",
path);
89 fprintf(stderr,
"timeout connecting to %s: %s\n",
90 path, strerror(errno));
95 nanosleep(&dur, NULL);
107 char ctlpath[PATH_MAX];
108 if (snprintf(ctlpath, PATH_MAX,
"%s/.dillo/ctl",
dGethomedir()) >= PATH_MAX) {
109 fprintf(stderr,
"path too long\n");
114 DIR *
dp = opendir(ctlpath);
116 fprintf(stderr,
"error: cannot open %s directory: %s\n",
117 ctlpath, strerror(errno));
118 fprintf(stderr,
"hint: is dillo running?\n");
123 struct sockaddr_un addr;
124 addr.sun_family = AF_UNIX;
126 while ((ep = readdir (
dp)) != NULL) {
127 const char *num = ep->d_name;
129 if (!strcmp(num,
".") || !strcmp(num,
".."))
136#define LEN ((int) sizeof(addr.sun_path))
137 if (snprintf(addr.sun_path,
LEN,
"%s/%s", ctlpath, num) >=
LEN) {
138 fprintf(stderr,
"pid path too long\n");
144 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
145 fprintf(stderr,
"socket() failed: %s\n", strerror(errno));
151 ret = connect(fd, (
struct sockaddr *) &addr,
sizeof(addr));
152 }
while (ret == -1 && errno == EINTR);
155 if (++found_pid == 1) {
162 if (errno == ECONNREFUSED) {
164 remove(addr.sun_path);
166 fprintf(stderr,
"cannot connect to %s, skipping: %s\n",
167 addr.sun_path, strerror(errno));
171 if (fd != -1 &&
dClose(fd) != 0) {
172 fprintf(stderr,
"cannot close fd: %s", strerror(errno));
181 else if (found_pid == 0) {
182 fprintf(stderr,
"error: cannot find ctl socket, is dillo running?\n");
186 fprintf(stderr,
"multiple ctl sockets found, set DILLO_PID\n");
195 char *given_pid = getenv(
"DILLO_PID");
213int main(
int argc,
char *argv[])
216 fprintf(stderr,
"missing command, try 'dilloc help'\n");
225 if (argv[1] && (!strcmp(argv[1],
"load") || !strcmp(argv[1],
"rawload"))) {
230 for (
int i = 1; i < argc; i++) {
238 for (ssize_t w = 0; w < cmd->
len; ) {
239 w = write(fd, cmd->
str + w, cmd->
len - w);
241 perror(
"write command to socket failed");
252 ssize_t r = read(STDIN_FILENO, buf,
BUFSIZ);
256 perror(
"read stdin failed");
263 ssize_t w = write(fd, p, r);
265 perror(
"write stdin to socket failed");
283 ssize_t r = read(fd, buf,
BUFSIZ);
287 perror(
"read reply failed");
296 fprintf(stderr,
"malformed reply: expected digit at first byte (got %c)\n", ch);
299 if (buf[1] !=
'\n') {
300 fprintf(stderr,
"malformed reply: expected newline at second byte\n");
310 ssize_t w = write(STDOUT_FILENO, p, r);
311 if (w < 0 && errno != EINTR) {
312 perror(
"cannot write reply to stdout");
static double get_time_s(void)
static int find_working_socket(int *sock)
static int is_number(const char *str)
static int connect_to_dillo(int *sock)
static int connect_given_pid(int *sock, const char *pid)
void dStr_append(Dstr *ds, const char *s)
Append a C string to a Dstr.
void dStr_free(Dstr *ds, int all)
Free a dillo string.
int dClose(int fd)
Close a FD handling EINTR.
void dStr_append_c(Dstr *ds, int c)
Append one character.
Dstr * dStr_new(const char *s)
Create a new string.
char * dGethomedir(void)
Return the home directory in a static string (don't free)
static int dIsdigit(unsigned char c)