├── README.md ├── samples ├── daemon.c └── client.c └── ipc.h /README.md: -------------------------------------------------------------------------------- 1 | # ipc.h 2 | A very simple API for interprocess communication using Unix Domain Sockets 3 | 4 | ## Using ipc.h 5 | Simply include `ipc.h` in your C files. 6 | 7 | See `samples/` for a client -> echo server example. 8 | 9 | ## Copyright 10 | Do What The Fuck Your Want To Public License (WTFPL) 11 | 12 | -------------------------------------------------------------------------------- /samples/daemon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "ipc.h" 9 | 10 | int main(int argc, char *argv[]) { 11 | 12 | ipc_server srv = ipc_create("echo_socket"); 13 | 14 | char buf[128]; 15 | while (1) { 16 | /* call accept */ 17 | puts("waiting for connection"); 18 | ipc_server_accept(&srv); 19 | puts("connected!"); 20 | 21 | /* handle connection and loop back to accept*/ 22 | while (ipc_server_read(&srv, buf, 128)) { 23 | printf("-> '%.*s'\n", srv.msglen - 1, buf); 24 | if (!strncmp(buf, "end", 3)) { 25 | puts("closing"); 26 | ipc_server_close(srv); 27 | exit(0); 28 | } 29 | 30 | ipc_server_send(&srv, buf, srv.msglen); 31 | } 32 | puts("client closed connection"); 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /samples/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "ipc.h" 9 | 10 | void handle_error(ipc_status err) { 11 | switch (err) { 12 | case IPC_SOCKET_ERROR: 13 | puts("socket call failed"); 14 | break; 15 | case IPC_CONNECT_FAILED: 16 | puts("socket connection failed. is the daemon running?"); 17 | break; 18 | }; 19 | } 20 | 21 | int main(int argc, char *argv[]) { 22 | 23 | /* connect to socket*/ 24 | ipc_client cli = ipc_connect("echo_socket"); 25 | if (cli.error) { 26 | handle_error(cli.error); 27 | return 1; 28 | } 29 | 30 | char str[128]; 31 | while (printf(">"), fgets(str, 128, stdin), !feof(stdin)) { 32 | ipc_client_send(&cli, str, strlen(str)); 33 | 34 | if (ipc_client_read(&cli, str, 128)) { 35 | printf("server> %s", str); 36 | } else { 37 | if (cli.t < 0) puts("error on recv"); 38 | else 39 | puts("Server closed connection"); 40 | return 1; 41 | } 42 | } 43 | ipc_client_close(cli); 44 | 45 | return 0; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /ipc.h: -------------------------------------------------------------------------------- 1 | #ifndef IPC_H 2 | #define IPC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | * Inter Process Communication server 14 | */ 15 | typedef struct { 16 | unsigned int s, s2; 17 | struct sockaddr_un local, remote; 18 | unsigned int msglen; 19 | } ipc_server; 20 | 21 | /* create unix domain socket inter process communication server */ 22 | ipc_server ipc_create(const char *path) { 23 | ipc_server srv; 24 | srv.s = socket(AF_UNIX, SOCK_STREAM, 0); 25 | 26 | /* bind */ 27 | srv.local.sun_family = AF_UNIX; 28 | strcpy(srv.local.sun_path, path); 29 | unlink(srv.local.sun_path); 30 | srv.msglen = strlen(srv.local.sun_path) + sizeof(srv.local.sun_family); 31 | 32 | bind(srv.s, (struct sockaddr *)&srv.local, srv.msglen); 33 | 34 | /* listen */ 35 | listen(srv.s, 5); 36 | return srv; 37 | } 38 | 39 | /* accept ipc client */ 40 | void ipc_server_accept(ipc_server *srv) { 41 | srv->msglen = sizeof(srv->remote); 42 | srv->s2 = accept(srv->s, (struct sockaddr *)&(srv->remote), &srv->msglen); 43 | } 44 | 45 | /* read from ipc server */ 46 | int ipc_server_read(ipc_server *srv, char *buf, int buflen) { 47 | srv->msglen = recv(srv->s2, buf, buflen, 0); 48 | return srv->msglen > 0; 49 | } 50 | 51 | /* write to ipc client */ 52 | void ipc_server_send(ipc_server *srv, char *buf, int buflen) { 53 | send(srv->s2, buf, buflen, 0); 54 | } 55 | 56 | /* close srv */ 57 | void ipc_server_close(ipc_server srv) { 58 | close(srv.s2); 59 | } 60 | 61 | /* 62 | * Inter Process Communication client 63 | */ 64 | 65 | typedef enum { 66 | IPC_OK = 0, 67 | IPC_UNKNOWN, 68 | IPC_SOCKET_ERROR, 69 | IPC_CONNECT_FAILED 70 | } ipc_status; 71 | 72 | typedef struct { 73 | int s, t, len; 74 | struct sockaddr_un remote; 75 | 76 | /* status */ 77 | ipc_status error; 78 | } ipc_client; 79 | 80 | ipc_client ipc_connect(const char *path) { 81 | ipc_client cli; 82 | cli.error = IPC_UNKNOWN; 83 | 84 | cli.s = socket(AF_UNIX, SOCK_STREAM, 0); 85 | if (cli.s == -1) { 86 | cli.error = IPC_SOCKET_ERROR; 87 | return cli; 88 | } 89 | 90 | cli.remote.sun_family = AF_UNIX; 91 | strcpy(cli.remote.sun_path, path); 92 | cli.len = strlen(cli.remote.sun_path) + sizeof(cli.remote.sun_family); 93 | if (connect(cli.s, (struct sockaddr *)&cli.remote, cli.len) == -1) { 94 | cli.error = IPC_CONNECT_FAILED; 95 | return cli; 96 | } 97 | 98 | cli.error = IPC_OK; 99 | return cli; 100 | } 101 | 102 | /* sends ipc data */ 103 | int ipc_client_send(ipc_client *cli, char *buf, int buflen) { 104 | return send(cli->s, buf, buflen, 0); 105 | } 106 | 107 | /* read ipc data */ 108 | int ipc_client_read(ipc_client *cli, char *buf, int buflen) { 109 | cli->t = recv(cli->s, buf, buflen, 0); 110 | return cli->t > 0; 111 | } 112 | 113 | /* close ipc socket */ 114 | void ipc_client_close(ipc_client cli) { 115 | close(cli.s); 116 | } 117 | 118 | #endif 119 | --------------------------------------------------------------------------------