+void fio_clients_terminate(void)
+{
+ struct flist_head *entry;
+ struct fio_client *client;
+
+ dprint(FD_NET, "client: terminate clients\n");
+
+ flist_for_each(entry, &client_list) {
+ client = flist_entry(entry, struct fio_client, list);
+
+ fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_QUIT, 0, NULL);
+ }
+}
+
+static void sig_int(int sig)
+{
+ dprint(FD_NET, "client: got signal %d\n", sig);
+ fio_clients_terminate();
+}
+
+static void sig_show_status(int sig)
+{
+ show_running_run_stats();
+}
+
+static void client_signal_handler(void)
+{
+ struct sigaction act;
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sig_int;
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGINT, &act, NULL);
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sig_int;
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGTERM, &act, NULL);
+
+/* Windows uses SIGBREAK as a quit signal from other applications */
+#ifdef WIN32
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sig_int;
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGBREAK, &act, NULL);
+#endif
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sig_show_status;
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGUSR1, &act, NULL);
+}
+
+static void probe_client(struct fio_client *client)
+{
+ dprint(FD_NET, "client: send probe\n");
+
+ fio_net_send_simple_cmd(client->fd, FIO_NET_CMD_PROBE, 0, &client->cmd_list);
+}
+
+static int send_client_cmd_line(struct fio_client *client)
+{
+ struct cmd_single_line_pdu *cslp;
+ struct cmd_line_pdu *clp;
+ unsigned long offset;
+ unsigned int *lens;
+ void *pdu;
+ size_t mem;
+ int i, ret;
+
+ dprint(FD_NET, "client: send cmdline %d\n", client->argc);
+
+ lens = malloc(client->argc * sizeof(unsigned int));
+
+ /*
+ * Find out how much mem we need
+ */
+ for (i = 0, mem = 0; i < client->argc; i++) {
+ lens[i] = strlen(client->argv[i]) + 1;
+ mem += lens[i];
+ }
+
+ /*
+ * We need one cmd_line_pdu, and argc number of cmd_single_line_pdu
+ */
+ mem += sizeof(*clp) + (client->argc * sizeof(*cslp));
+
+ pdu = malloc(mem);
+ clp = pdu;
+ offset = sizeof(*clp);
+
+ for (i = 0; i < client->argc; i++) {
+ uint16_t arg_len = lens[i];
+
+ cslp = pdu + offset;
+ strcpy((char *) cslp->text, client->argv[i]);
+ cslp->len = cpu_to_le16(arg_len);
+ offset += sizeof(*cslp) + arg_len;
+ }
+
+ free(lens);
+ clp->lines = cpu_to_le16(client->argc);
+ ret = fio_net_send_cmd(client->fd, FIO_NET_CMD_JOBLINE, pdu, mem, 0);
+ free(pdu);
+ return ret;
+}
+