Updated tomd and tomc to do solid communication over sockets.
[tlb/tomd.git] / src / tomc / main.c
CommitLineData
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
26static int sfd;
27
805d0ff4
TB
28static 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
34static 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
56static char *default_name = "no_name";
57static struct{
58 char status, stop, kill, start;
59 char *name;
60} options;
61
62static 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 95static 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
106static char write_buf[100];
107static 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
147static void write_client(void)
148{
149 SOCK_WRITE("client:tomc");
150 SOCK_ACK;
151}
152
952aba97
TB
153static 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
182int 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}