FOSSology  4.4.0
Open Source License Compliance by Open Source Software
fo_cli.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2010, 2011, 2012 Hewlett-Packard Development Company, L.P.
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
11 /* std library includes */
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 /* unix includes */
17 #include <ctype.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <pwd.h>
21 #include <sys/socket.h>
22 #include <sys/types.h>
23 #include <netinet/in.h>
24 #include <netdb.h>
25 #include <unistd.h>
26 
27 /* other library includes */
28 #include <libfossology.h>
29 #include <glib.h>
30 
31 #define P_WIDTH 27
32 #define F_WIDTH 10
33 
34 #define vprintf(...) if(verbose) printf(__VA_ARGS__);
35 
36 int response = 1;
37 int s;
38 int verbose;
40 
41 /* ************************************************************************** */
42 /* **** utility functions *************************************************** */
43 /* ************************************************************************** */
44 
54 int socket_connect(char* host, char* port)
55 {
56  int fd;
57  struct addrinfo hints;
58  struct addrinfo* servs, * curr = NULL;
59 
60  memset(&hints, 0, sizeof(hints));
61  hints.ai_family = AF_UNSPEC;
62  hints.ai_socktype = SOCK_STREAM;
63  if(getaddrinfo(host, port, &hints, &servs) == -1)
64  {
65  fprintf(stderr, "ERROR: %s.%d: unable to connect to %s port: %s\n",
66  __FILE__, __LINE__, host, port);
67  fprintf(stderr, "ERROR: errno: %s\n", strerror(errno));
68  return -1;
69  }
70 
71  for(curr = servs; curr != NULL; curr = curr->ai_next)
72  {
73  if((fd = socket(curr->ai_family, hints.ai_socktype, curr->ai_protocol)) < 0)
74  continue;
75 
76  if(connect(fd, curr->ai_addr, curr->ai_addrlen) == -1)
77  continue;
78 
79  break;
80  }
81 
82  if(curr == NULL)
83  {
84  fprintf(stderr, "ERROR: %s.%d: unable to connect to %s port: %s\n",
85  __FILE__, __LINE__, host, port);
86  return -1;
87  }
88 
89  freeaddrinfo(servs);
90  return fd;
91 }
92 
102 uint8_t receive(int s, char* buffer, size_t max, uint8_t end)
103 {
104  size_t bytes = 0;
105  uint8_t closing = 0;
106  char* poss;
107 
108  do
109  {
110  /* start by clearing the buffer */
111  memset(buffer, '\0', max);
112  bytes = 0;
113 
114  /* read from the socket */
115  do
116  {
117  bytes = read(s, buffer + bytes, max - bytes);
118 
119  if(bytes == 0)
120  {
121  printf("ERROR: connection to scheduler closed\nERROR: closing cli\n");
122  closing = 1;
123  }
124 
125  bytes = strlen(buffer);
126  } while(!closing && buffer[bytes - 1] != '\n');
127 
128  /* interpret the results */
129  for(poss = strtok(buffer, "\n"); !closing && poss != NULL;
130  poss = strtok(NULL, "\n"))
131  {
132  if(strncmp(poss, "received", 8) == 0)
133  {
134  if(response)
135  printf("Command received\n");
136  }
137  else if(strncmp(poss, "CLOSE", 5) == 0)
138  {
139  closing = 1;
140  }
141  else if(strcmp(poss, "end") != 0)
142  {
143  printf("%s\n", poss);
144  }
145  else
146  {
147  end = 0;
148  }
149  }
150 
151  fflush(stdout);
152  } while(end);
153 
154  return closing;
155 }
156 
163 {
164  printf("FOSSology scheduler command line interface\n");
165  printf("+-----------------------------------------------------------------------------+\n");
166  printf("|%*s: EFFECT |\n", P_WIDTH, "CMD [optional] <required>");
167  printf("+-----------------------------------------------------------------------------+\n");
168  printf("|%*s: prints this usage statement |\n", P_WIDTH, "help");
169  printf("|%*s: close the connection and exit cli |\n", P_WIDTH, "close");
170  printf("|%*s: shutdown will wait for agents be stopping |\n", P_WIDTH, "stop");
171  printf("|%*s: shutdown will shutdown immediately |\n", P_WIDTH, "die");
172  printf("|%*s: get load information for host machines |\n", P_WIDTH, "load");
173  printf("|%*s: kills a currently running job (ungraceful) |\n", P_WIDTH, "kill <jq_pk> <\"message\">");
174  printf("|%*s: pauses a job indefinitely |\n", P_WIDTH, "pause <jq_pk>");
175  printf("|%*s: reload the configuration information |\n", P_WIDTH, "reload");
176  printf("|%*s: prints a list of valid agents |\n", P_WIDTH, "agents");
177  printf("|%*s: scheduler responds with status information |\n", P_WIDTH, "status [jq_pk]");
178  printf("|%*s: restart a paused job |\n", P_WIDTH, "restart <jq_pk>");
179  printf("|%*s: query/change the scheduler/job verbosity |\n", P_WIDTH, "verbose [jq_pk] [level]");
180  printf("|%*s: change priority for job that this jq_pk is in |\n", P_WIDTH, "priority <jq_pk> <level>");
181  printf("|%*s: causes the scheduler to check the job queue |\n", P_WIDTH, "database");
182  printf("+-----------------------------------------------------------------------------+\n");
183  fflush(stdout);
184 }
185 
186 /* ************************************************************************** */
187 /* **** main **************************************************************** */
188 /* ************************************************************************** */
189 
190 int main(int argc, char** argv)
191 {
192  /* local variables */
193  fd_set fds; // file descriptor set used in select statement
194  int closing; // flags and loop variables
195  size_t bytes; // variable to capture return of read
196  char* host; // string to hold the name of the host
197  char* port; // string port number to connect to
198  char buffer[1024]; // string buffer used to read
199  char* config; // FOSSology configuration directory
200  GOptionContext* options; // the command line options parser
201  GError* error = NULL;
202 
203  /* command bool and info */
204  uint8_t c_die = 0;
205  uint8_t c_stop = 0;
206  uint8_t c_load = 0;
207  uint8_t c_pause = 0;
208  uint8_t c_reload = 0;
209  uint8_t c_status = 0;
210  uint8_t c_agents = 0;
211  uint8_t c_restart = 0;
212  uint8_t c_verbose = 0;
213  uint8_t c_database = 0;
214 
215  /* initialize memory */
216  host = NULL;
217  port = NULL;
218  config = DEFAULT_SETUP;
219  memset(buffer, '\0', sizeof(buffer));
220  closing = 0;
221  verbose = 0;
222 
223  GOptionEntry entries[] =
224  {
225  {"config", 'c', 0, G_OPTION_ARG_STRING, &config,
226  "Set the directory for the system configuration", "string"},
227  {"host", 'H', 0, G_OPTION_ARG_STRING, &host,
228  "Set the host that the scheduler is on", "string"},
229  {"port", 'p', 0, G_OPTION_ARG_STRING, &port,
230  "Set the port that the scheduler is listening on", "integer"},
231  {"quiet", 'q', 0, G_OPTION_ARG_NONE, &verbose,
232  "Cause the CLI to not print usage hints", NULL},
233  {"load", 'l', 0, G_OPTION_ARG_NONE, &c_load,
234  "CLI will send a load command and close"},
235  {"agents", 'a', 0, G_OPTION_ARG_NONE, &c_agents,
236  "CLI will send an agents command and close"},
237  {"status", 'S', 0, G_OPTION_ARG_NONE, &c_status,
238  "CLI will send a status command and close"},
239  {"stop", 's', 0, G_OPTION_ARG_NONE, &c_stop,
240  "CLI will send stop command and close", NULL},
241  {"die", 'D', 0, G_OPTION_ARG_NONE, &c_die,
242  "CLI will send a die command and close"},
243  {"pause", 'P', 0, G_OPTION_ARG_INT, &c_pause,
244  "CLI will send a pause command and close", "integer"},
245  {"reload", 'r', 0, G_OPTION_ARG_NONE, &c_reload,
246  "CLI will send a reload command and close", NULL},
247  {"restart", 'R', 0, G_OPTION_ARG_INT, &c_restart,
248  "CLI will send a restart command and close", "integer"},
249  {"verbose", 'v', 0, G_OPTION_ARG_INT, &c_verbose,
250  "CLI will change the scheduler's verbose level", "integer"},
251  {"database", 'd', 0, G_OPTION_ARG_NONE, &c_database,
252  "CLI will send a database command to scheduler", NULL},
253  {NULL}
254  };
255 
256  options = g_option_context_new("- command line tool for FOSSology scheduler");
257  g_option_context_add_main_entries(options, entries, NULL);
258  g_option_context_set_ignore_unknown_options(options, FALSE);
259  g_option_context_parse(options, &argc, &argv, &error);
260 
261  if(error)
262  {
263  config = g_option_context_get_help(options, FALSE, NULL);
264  fprintf(stderr, "ERROR: %s\n%s", error->message, config);
265  g_free(config);
266  return -1;
267  }
268 
269  g_option_context_free(options);
270 
271  /* set the basic configuration */
272  /* change the verbose to conform to quite option */
273  verbose = !verbose;
274 
275  snprintf(buffer, sizeof(buffer), "%s/fossology.conf", config);
276  conf = fo_config_load(buffer, &error);
277  if(error)
278  {
279  fprintf(stderr, "ERROR: %s.%d: error loading config: %s\n",
280  __FILE__, __LINE__, error->message);
281  return -1;
282  }
283 
284  /* check the scheduler config for port number */
285  if(port == NULL)
286  port = fo_config_get(conf, "FOSSOLOGY", "port", &error);
287  if(!error && host == NULL)
288  host = fo_config_get(conf, "FOSSOLOGY", "address", &error);
289 
290  /* open the connection to the scheduler */
291  if((s = socket_connect(host, port)) < 0)
292  return -1;
293 
294  /* check specific command instructions */
295  if(c_die || c_stop || c_load || c_pause || c_reload || c_status || c_agents
296  || c_restart || c_verbose || c_database)
297  {
298  response = 0;
299 
300  /* simple no parameter commands */
301  if(c_reload)
302  bytes = write(s, "reload", 6);
303  if(c_database)
304  bytes = write(s, "database", 8);
305  if(c_stop)
306  bytes = write(s, "stop", 4);
307  if(c_die)
308  bytes = write(s, "die", 3);
309 
310  /* simple commands that require a parameter */
311  if(c_verbose)
312  {
313  snprintf(buffer, sizeof(buffer) - 1, "verbose %d", c_verbose);
314  bytes = write(s, buffer, strlen(buffer));
315  }
316 
317  if(c_pause)
318  {
319  snprintf(buffer, sizeof(buffer) - 1, "pause %d", c_pause);
320  bytes = write(s, buffer, strlen(buffer));
321  }
322 
323  if(c_restart)
324  {
325  snprintf(buffer, sizeof(buffer) - 1, "restart %d", c_restart);
326  bytes = write(s, buffer, strlen(buffer));
327  }
328 
329  /* requests for information */
330  if(c_load)
331  {
332  bytes = write(s, "load", 4);
333  receive(s, buffer, sizeof(buffer), TRUE);
334  }
335 
336  if(c_status)
337  {
338  bytes = write(s, "status", 6);
339  receive(s, buffer, sizeof(buffer), TRUE);
340  }
341 
342  if(c_agents)
343  {
344  bytes = write(s, "agents", 6);
345  receive(s, buffer, sizeof(buffer), TRUE);
346  }
347 
348  return 0;
349  }
350 
351  /* listen to the scheulder */
352  if(verbose)
353  interface_usage();
354  while(!closing)
355  {
356  /* prepare for read */
357  FD_ZERO(&fds);
358  FD_SET(s, &fds);
359  FD_SET(fileno(stdin), &fds);
360  memset(buffer, '\0', sizeof(buffer));
361  select(s + 1, &fds, NULL, NULL, NULL);
362 
363  /* check the socket */
364  if(FD_ISSET(s, &fds))
365  closing = receive(s, buffer, sizeof(buffer), FALSE);
366 
367  /* check stdin */
368  if(FD_ISSET(fileno(stdin), &fds))
369  {
370  if(read(fileno(stdin), buffer, sizeof(buffer)) == 0)
371  break;
372 
373  if(strcmp(buffer, "help\n") == 0)
374  {
375  interface_usage();
376  continue;
377  }
378 
379  response = (strncmp(buffer, "agents", 6) == 0 ||
380  strncmp(buffer, "status", 6) == 0 ||
381  strcmp (buffer, "verbose\n" ) == 0 ||
382  strcmp (buffer, "load\n" ) == 0) ?
383  FALSE : TRUE;
384 
385  if((bytes = write(s, buffer, strlen(buffer) - 1)) != strlen(buffer) - 1)
386  {
387  printf("ERROR: couldn't write %lu bytes to socket\n", bytes);
388  closing = 1;
389  }
390  }
391  }
392 
393  return 0;
394 }
uint8_t receive(int s, char *buffer, size_t max, uint8_t end)
Performs the actions necessary to receive from the scheduler.
Definition: fo_cli.c:102
int verbose
The verbose flag for the cli.
Definition: fo_cli.c:38
int response
Is a response expected from the scheduler.
Definition: fo_cli.c:36
int s
The socket that the CLI will use to communicate.
Definition: fo_cli.c:37
fo_conf * conf
The loaded configuration data.
Definition: fo_cli.c:39
void interface_usage()
Interface usage print.
Definition: fo_cli.c:162
int socket_connect(char *host, char *port)
Create a socket connection.
Definition: fo_cli.c:54
fo_conf * fo_config_load(char *rawname, GError **error)
Load the configuration information from the provided file.
Definition: fossconfig.c:275
char * fo_config_get(fo_conf *conf, const char *group, const char *key, GError **error)
Gets an element based on its group name and key name. If the group or key is not found,...
Definition: fossconfig.c:336
FUNCTION int max(int permGroup, int permPublic)
Get the maximum group privilege.
Definition: libfossagent.c:295
The main FOSSology C library.
char buffer[2048]
The last thing received from the scheduler.
int closing
Set if scheduler is shutting down.
Definition: scheduler.c:58