70fd273679bf170f7fd40fd29d2e4417f142beb3
1 /*
2 * syscollector - src/utils/unixsock.c
3 * Copyright (C) 2012 Sebastian 'tokkee' Harl <sh@tokkee.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
28 #include "utils/unixsock.h"
29 #include "utils/string.h"
31 #include <errno.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <strings.h>
37 #include <unistd.h>
39 #include <sys/socket.h>
40 #include <sys/un.h>
42 /*
43 * private data types
44 */
46 struct sc_unixsock_client {
47 char *path;
48 FILE *fh;
49 };
51 /*
52 * public API
53 */
55 sc_unixsock_client_t *
56 sc_unixsock_client_create(const char *path)
57 {
58 sc_unixsock_client_t *client;
60 if (! path)
61 return NULL;
63 client = malloc(sizeof(*client));
64 if (! client)
65 return NULL;
66 memset(client, 0, sizeof(*client));
67 client->fh = NULL;
69 client->path = strdup(path);
70 if (! client->path) {
71 sc_unixsock_client_destroy(client);
72 return NULL;
73 }
74 return client;
75 } /* sc_unixsock_client_create */
77 int
78 sc_unixsock_client_connect(sc_unixsock_client_t *client)
79 {
80 struct sockaddr_un sa;
81 int fd;
83 if ((! client) || (! client->path))
84 return -1;
86 memset(&sa, 0, sizeof(sa));
88 if (client->fh)
89 fclose(client->fh);
91 fd = socket(AF_UNIX, SOCK_STREAM, /* protocol = */ 0);
92 if (fd < 0) {
93 char errbuf[1024];
94 fprintf(stderr, "unixsock: Failed to open socket: %s\n",
95 sc_strerror(errno, errbuf, sizeof(errbuf)));
96 return -1;
97 }
99 sa.sun_family = AF_UNIX;
100 strncpy(sa.sun_path, client->path, sizeof(sa.sun_path));
101 sa.sun_path[sizeof(sa.sun_path) - 1] = '\0';
103 if (connect(fd, (struct sockaddr *)&sa, sizeof(sa))) {
104 char errbuf[1024];
105 fprintf(stderr, "unixsock: Failed to connect to %s: %s\n",
106 sa.sun_path, sc_strerror(errno, errbuf, sizeof(errbuf)));
107 close(fd);
108 return -1;
109 }
111 client->fh = fdopen(fd, "r+");
112 if (! client->fh) {
113 char errbuf[1024];
114 fprintf(stderr, "unixsock: Failed to open I/O stream for %s: %s\n",
115 sa.sun_path, sc_strerror(errno, errbuf, sizeof(errbuf)));
116 close(fd);
117 return -1;
118 }
119 return 0;
120 } /* sc_unixsock_client_connect */
122 int
123 sc_unixsock_client_send(sc_unixsock_client_t *client, const char *msg)
124 {
125 int status;
127 if ((! client) || (! client->fh))
128 return -1;
130 status = fprintf(client->fh, "%s\r\n", msg);
131 if (status < 0) {
132 char errbuf[1024];
133 fprintf(stderr, "unixsock: Failed to write to socket (%s): %s\n",
134 client->path, sc_strerror(errno, errbuf, sizeof(errbuf)));
135 return status;
136 }
137 return status;
138 } /* sc_unixsock_client_send */
140 char *
141 sc_unixsock_client_recv(sc_unixsock_client_t *client, char *buffer, size_t buflen)
142 {
143 if ((! client) || (! client->fh) || (! buffer))
144 return NULL;
146 buffer = fgets(buffer, (int)buflen - 1, client->fh);
147 if (! buffer) {
148 if (! feof(client->fh)) {
149 char errbuf[1024];
150 fprintf(stderr, "unixsock: Failed to read from socket (%s): %s\n",
151 client->path, sc_strerror(errno, errbuf, sizeof(errbuf)));
152 }
153 return buffer;
154 }
155 buffer[buflen - 1] = '\0';
157 buflen = strlen(buffer);
158 while ((buffer[buflen - 1] == '\n') || (buffer[buflen - 1] == '\r')) {
159 buffer[buflen - 1] = '\0';
160 --buflen;
161 }
162 return buffer;
163 } /* sc_unixsock_client_recv */
165 void
166 sc_unixsock_client_destroy(sc_unixsock_client_t *client)
167 {
168 if (! client)
169 return;
171 if (client->path)
172 free(client->path);
173 client->path = NULL;
175 if (client->fh)
176 fclose(client->fh);
177 client->fh = NULL;
179 free(client);
180 } /* sc_unixsock_client_destroy */
182 const char *
183 sc_unixsock_client_path(sc_unixsock_client_t *client)
184 {
185 if (! client)
186 return NULL;
187 return client->path;
188 } /* sc_unixsock_client_path */
190 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */