author | viric@llimona |
Tue, 27 Mar 2007 23:29:56 +0200 | |
changeset 58 | 3c492266923e |
parent 49 | 09bb8a5583e9 |
child 64 | 2a17c9c7b1d5 |
permissions | -rw-r--r-- |
49 | 1 |
/* |
2 |
Task Spooler - a task queue system for the unix user |
|
3 |
Copyright (C) 2007 LluĂs Batlle i Rossell |
|
4 |
||
5 |
Please find the license in the provided COPYING file. |
|
6 |
*/ |
|
44 | 7 |
#include <unistd.h> |
1 | 8 |
#include <assert.h> |
44 | 9 |
#include <string.h> |
1 | 10 |
#include <sys/types.h> |
11 |
#include <sys/socket.h> |
|
12 |
#include <sys/un.h> |
|
13 |
#include <errno.h> |
|
3 | 14 |
#include <stdlib.h> |
9 | 15 |
#include <stdio.h> |
25 | 16 |
#include <signal.h> |
3 | 17 |
|
18 |
#include "main.h" |
|
1 | 19 |
|
20 |
extern int server_socket; |
|
21 |
||
28
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
22 |
static char *path; |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
23 |
|
25 | 24 |
static int fork_server(); |
25 |
||
28
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
26 |
static void create_path() |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
27 |
{ |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
28 |
char *tmpdir; |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
29 |
char *username; |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
30 |
int size; |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
31 |
|
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
32 |
/* Create the path */ |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
33 |
tmpdir = getenv("TMPDIR"); |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
34 |
if (tmpdir == NULL) |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
35 |
tmpdir = "/tmp"; |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
36 |
|
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
37 |
username = getenv("USER"); |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
38 |
if (username == NULL) |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
39 |
username = "unknown"; |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
40 |
|
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
41 |
/* Calculate the size */ |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
42 |
size = strlen(tmpdir) + strlen("/socket-ts.") + strlen(username) + 1; |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
43 |
|
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
44 |
/* Freed after preparing the socket address */ |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
45 |
path = (char *) malloc(size); |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
46 |
|
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
47 |
sprintf(path, "%s/socket-ts.%s", tmpdir, username); |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
48 |
} |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
49 |
|
1 | 50 |
int try_connect(int s) |
51 |
{ |
|
2 | 52 |
struct sockaddr_un addr; |
53 |
int res; |
|
1 | 54 |
|
2 | 55 |
addr.sun_family = AF_UNIX; |
28
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
56 |
strcpy(addr.sun_path, path); |
1 | 57 |
|
2 | 58 |
res = connect(s, (struct sockaddr *) &addr, sizeof(addr)); |
59 |
return res; |
|
1 | 60 |
} |
61 |
||
25 | 62 |
void wait_server_up(int fd) |
1 | 63 |
{ |
25 | 64 |
char a; |
65 |
||
66 |
read(fd, &a, 1); |
|
67 |
close(fd); |
|
1 | 68 |
} |
69 |
||
25 | 70 |
/* Returns the fd where to wait for the parent notification */ |
71 |
static int fork_server() |
|
1 | 72 |
{ |
2 | 73 |
int pid; |
25 | 74 |
int p[2]; |
1 | 75 |
|
2 | 76 |
/* !!! stdin/stdout */ |
25 | 77 |
pipe(p); |
1 | 78 |
|
2 | 79 |
pid = fork(); |
80 |
switch (pid) |
|
81 |
{ |
|
82 |
case 0: /* Child */ |
|
25 | 83 |
close(p[0]); |
3 | 84 |
close(server_socket); |
28
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
85 |
server_main(p[1], path); |
3 | 86 |
exit(0); |
2 | 87 |
break; |
88 |
case -1: /* Error */ |
|
25 | 89 |
return -1; |
2 | 90 |
default: /* Parent */ |
25 | 91 |
close(p[1]); |
2 | 92 |
} |
25 | 93 |
/* Return the read fd */ |
94 |
return p[0]; |
|
95 |
} |
|
96 |
||
97 |
void notify_parent(int fd) |
|
98 |
{ |
|
99 |
char a = 'a'; |
|
100 |
write(fd, &a, 1); |
|
101 |
close(fd); |
|
1 | 102 |
} |
103 |
||
104 |
int ensure_server_up() |
|
105 |
{ |
|
2 | 106 |
int res; |
25 | 107 |
int notify_fd; |
1 | 108 |
|
2 | 109 |
server_socket = socket(PF_UNIX, SOCK_STREAM, 0); |
110 |
assert(server_socket != -1); |
|
1 | 111 |
|
28
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
112 |
create_path(); |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
113 |
|
2 | 114 |
res = try_connect(server_socket); |
1 | 115 |
|
2 | 116 |
/* Good connection */ |
117 |
if (res == 0) |
|
118 |
return 1; |
|
1 | 119 |
|
2 | 120 |
/* If error other than "No one listens on the other end"... */ |
3 | 121 |
if (!(errno == ENOENT || errno == ECONNREFUSED)) |
9 | 122 |
{ |
123 |
perror("c: cannot connect to the server"); |
|
124 |
exit(-1); |
|
125 |
} |
|
1 | 126 |
|
3 | 127 |
if (errno == ECONNREFUSED) |
28
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
128 |
unlink(path); |
3 | 129 |
|
2 | 130 |
/* Try starting the server */ |
25 | 131 |
notify_fd = fork_server(); |
132 |
wait_server_up(notify_fd); |
|
2 | 133 |
res = try_connect(server_socket); |
1 | 134 |
|
2 | 135 |
/* The second time didn't work. Abort. */ |
136 |
if (res == -1) |
|
9 | 137 |
{ |
138 |
fprintf(stderr, "The server didn't come up.\n"); |
|
139 |
exit(-1); |
|
140 |
} |
|
1 | 141 |
|
28
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
142 |
free(path); |
107abb4ec98a
Unified socket path, depending on the username and $TMPDIR.
viric@llimona
parents:
25
diff
changeset
|
143 |
|
2 | 144 |
/* Good connection on the second time */ |
145 |
return 1; |
|
1 | 146 |
} |