Commit | Line | Data |
---|---|---|
06570394 TB |
1 | /* Copyright (C) 2018 Thomas Balzer */ |
2 | ||
3 | /* This file is part of tomd. */ | |
4 | ||
5 | /* tomd is free software: you can redistribute it and/or modify */ | |
6 | /* it under the terms of the GNU General Public License as published by */ | |
7 | /* the Free Software Foundation, either version 3 of the License, or */ | |
8 | /* (at your option) any later version. */ | |
9 | ||
10 | /* tomd is distributed in the hope that it will be useful, */ | |
11 | /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ | |
12 | /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ | |
13 | /* GNU General Public License for more details. */ | |
14 | ||
15 | /* You should have received a copy of the GNU General Public License */ | |
16 | /* along with tomd. If not, see <http://www.gnu.org/licenses/>. */ | |
17 | ||
18 | #include <stdlib.h> | |
19 | #include <stdio.h> | |
20 | #include <sys/un.h> | |
21 | #include <sys/socket.h> | |
22 | #include <unistd.h> | |
23 | ||
4dafa6fe TB |
24 | #include "../../include/macros.h" |
25 | ||
06570394 TB |
26 | static int sfd; |
27 | ||
805d0ff4 TB |
28 | static void header(void) |
29 | { | |
30 | tomc_p("Tom's Client, Copyright (C) 2018 Thomas Balzer"); | |
31 | tomc_p("GPL v3 or later license."); | |
32 | } | |
33 | ||
06570394 TB |
34 | static void init(void) |
35 | { | |
36 | /* init socket connection */ | |
37 | sfd = | |
38 | socket(PF_LOCAL, | |
39 | SOCK_STREAM, | |
40 | 0); | |
41 | if(sfd < 0){ | |
42 | perror("socket"); | |
43 | exit(EXIT_FAILURE); | |
44 | } | |
45 | ||
46 | struct sockaddr_un addr; | |
47 | addr.sun_family = AF_LOCAL; | |
48 | sprintf(addr.sun_path, "/run/user/1000/tomd/socket"); | |
49 | ||
50 | if(connect(sfd, (struct sockaddr *) &addr, SUN_LEN(&addr)) != 0){ | |
51 | perror("connect"); | |
52 | exit(EXIT_FAILURE); | |
53 | } | |
54 | } | |
55 | ||
805d0ff4 TB |
56 | static char *default_name = "no_name"; |
57 | static struct{ | |
58 | char status, stop, kill, start; | |
59 | char *name; | |
60 | } options; | |
61 | ||
62 | static void extract_options(int argc, char **argv) | |
63 | { | |
64 | /* -status <name> Get status - if we thought we ran it, current real status */ | |
65 | /* -stop <name> Run provided command to gently stop */ | |
66 | /* -kill <name> Aggressive killing of process (signal 15) */ | |
67 | /* -start <name> Run name */ | |
68 | if(argc == 1){ | |
69 | /* only tomc given */ | |
70 | tomc_p("no args given."); | |
71 | exit(EXIT_SUCCESS); | |
72 | } | |
73 | ||
74 | options.name = NULL; | |
75 | ||
76 | for(int i = 1; | |
77 | i < argc; | |
78 | i++){ | |
79 | char *arg = argv[i]; | |
80 | #define X(op) {if(strcmp("-" #op, arg) == 0){options.op = 1; continue;}} | |
81 | X(status); | |
82 | X(stop); | |
83 | X(kill); | |
84 | X(start); | |
85 | #undef X | |
86 | /* assume last non option was the name */ | |
87 | options.name = arg; | |
88 | } | |
89 | ||
90 | if(options.name == NULL){ | |
91 | options.name = default_name; | |
92 | } | |
93 | } | |
94 | ||
952aba97 | 95 | static void print_options(void) |
06570394 | 96 | { |
805d0ff4 TB |
97 | tomc_p("---------"); |
98 | tomc_p(" name: %s", options.name); | |
99 | tomc_p(" kill: %d", options.kill); | |
100 | tomc_p("status: %d", options.status); | |
101 | tomc_p(" stop: %d", options.stop); | |
102 | tomc_p(" start: %d", options.start); | |
103 | tomc_p("---------"); | |
06570394 TB |
104 | } |
105 | ||
952aba97 TB |
106 | static char write_buf[100]; |
107 | static char socket_buf[100]; | |
108 | ||
109 | #define SOCK_WRITE(X) { \ | |
110 | strcpy(write_buf, X); \ | |
111 | int write_len = strlen(write_buf); \ | |
112 | ssize_t wrote = \ | |
113 | write(sfd, write_buf, write_len); \ | |
81215080 | 114 | tomc_p("wrote '%s' (%d)", write_buf, write_len); \ |
952aba97 TB |
115 | if(wrote != write_len){ \ |
116 | perror("[tomc] write size mismatch"); \ | |
117 | exit(EXIT_FAILURE); \ | |
81215080 TB |
118 | }} |
119 | ||
120 | ||
121 | #define SOCK_READ { \ | |
122 | int size = read(sfd, socket_buf, 100); \ | |
123 | if(read == 0) { \ | |
124 | tomc_p("didn't actually get anything."); \ | |
125 | socket_buf[0] = '\0'; \ | |
126 | } \ | |
127 | socket_buf[size] = '\0'; \ | |
952aba97 | 128 | } |
952aba97 TB |
129 | #define SOCK_READ_X(X){ \ |
130 | SOCK_READ; \ | |
131 | if(strcmp(socket_buf, X) != 0){ \ | |
132 | tomc_p("protocol error. instead of ACK we got '%s'", socket_buf); \ | |
133 | exit(EXIT_FAILURE); \ | |
134 | } \ | |
81215080 | 135 | tomc_p("got an ACK"); \ |
952aba97 TB |
136 | } |
137 | #define SOCK_ACK {SOCK_READ_X("ACK")}; | |
138 | #define SOCK_REQUEST(X) { \ | |
139 | SOCK_WRITE(X); \ | |
140 | SOCK_ACK; \ | |
141 | SOCK_WRITE(options.name); \ | |
142 | SOCK_ACK; \ | |
143 | SOCK_READ; \ | |
144 | tomc_p("tomd reports '%s'", socket_buf); \ | |
145 | } | |
146 | ||
147 | static void write_client(void) | |
148 | { | |
149 | SOCK_WRITE("client:tomc"); | |
150 | SOCK_ACK; | |
151 | } | |
152 | ||
952aba97 TB |
153 | static void write_requests(void) |
154 | { | |
155 | write_client(); | |
156 | ||
157 | /* go through options to figure out what we want to do */ | |
158 | if(options.kill){ | |
159 | SOCK_REQUEST("kill"); | |
160 | ||
161 | if(options.start == 1 || | |
162 | options.stop == 1){ | |
163 | tomc_p("can only kill and status at once."); | |
164 | } | |
165 | } else { | |
166 | if(options.start){ | |
167 | if(options.stop){ | |
168 | tomc_p("can't start and stop at once."); | |
169 | } | |
170 | SOCK_REQUEST("start"); | |
171 | } | |
172 | if(options.stop){ | |
173 | SOCK_REQUEST("stop"); | |
174 | } | |
175 | } | |
176 | ||
177 | if(options.status){ | |
178 | SOCK_REQUEST("status"); | |
179 | } | |
180 | } | |
181 | ||
06570394 TB |
182 | int main(int argc, char **argv) |
183 | { | |
184 | header(); | |
805d0ff4 TB |
185 | extract_options(argc, argv); |
186 | print_options(); | |
06570394 | 187 | init(); |
952aba97 | 188 | write_requests(); |
06570394 TB |
189 | |
190 | return EXIT_SUCCESS; | |
191 | } |