2 #include "unix-socket.h"
4 static int unix_stream_socket(void)
6 int fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
8 die_errno("unable to create socket");
12 static int chdir_len(const char *orig
, int len
)
14 char *path
= xmemdupz(orig
, len
);
20 struct unix_sockaddr_context
{
21 char orig_dir
[PATH_MAX
];
24 static void unix_sockaddr_cleanup(struct unix_sockaddr_context
*ctx
)
26 if (!ctx
->orig_dir
[0])
29 * If we fail, we can't just return an error, since we have
30 * moved the cwd of the whole process, which could confuse calling
31 * code. We are better off to just die.
33 if (chdir(ctx
->orig_dir
) < 0)
34 die("unable to restore original working directory");
37 static int unix_sockaddr_init(struct sockaddr_un
*sa
, const char *path
,
38 struct unix_sockaddr_context
*ctx
)
40 int size
= strlen(path
) + 1;
42 ctx
->orig_dir
[0] = '\0';
43 if (size
> sizeof(sa
->sun_path
)) {
44 const char *slash
= find_last_dir_sep(path
);
54 size
= strlen(path
) + 1;
55 if (size
> sizeof(sa
->sun_path
)) {
60 if (!getcwd(ctx
->orig_dir
, sizeof(ctx
->orig_dir
))) {
64 if (chdir_len(dir
, slash
- dir
) < 0)
68 memset(sa
, 0, sizeof(*sa
));
69 sa
->sun_family
= AF_UNIX
;
70 memcpy(sa
->sun_path
, path
, size
);
74 int unix_stream_connect(const char *path
)
77 struct sockaddr_un sa
;
78 struct unix_sockaddr_context ctx
;
80 if (unix_sockaddr_init(&sa
, path
, &ctx
) < 0)
82 fd
= unix_stream_socket();
83 if (connect(fd
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0)
85 unix_sockaddr_cleanup(&ctx
);
90 unix_sockaddr_cleanup(&ctx
);
96 int unix_stream_listen(const char *path
)
99 struct sockaddr_un sa
;
100 struct unix_sockaddr_context ctx
;
104 if (unix_sockaddr_init(&sa
, path
, &ctx
) < 0)
106 fd
= unix_stream_socket();
108 if (bind(fd
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0)
111 if (listen(fd
, 5) < 0)
114 unix_sockaddr_cleanup(&ctx
);
119 unix_sockaddr_cleanup(&ctx
);