1 /*-
2  * Copyright (c) 2006. Ivan Voras <ivoras@gmail.com>
3  * Released under the Artistic License
4  */
5 
6 /*
7  * sqlcached diagnostic/debugging/testing client
8  * $Id: client.c,v 1.3 2007/04/25 10:17:04 ivoras Exp $
9  */
10 
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/socket.h>
14 #include <sys/un.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <readline/readline.h>
21 #include <readline/history.h>
22 
23 #include "common.h"
24 #include "sqlcached_client.h"
25 
26 static char* unix_socket_name = DEFAULT_UNIX_SOCKET;
27 
28 int argc;
29 char **argv;
30 
31 struct sc_client_conn sc;
32 static char* whitespace = " \t";
33 
34 
35 /** Shows help message */
show_help()36 static void show_help() {
37     printf("usage: %s [-h] | [-u unix_socket_name]\n", argv[0]);
38     printf("        -h :                    Show this help message\n");
39     printf("        -u unix_socket_name :   Set unix socket name of sqlcached (default %s)", DEFAULT_UNIX_SOCKET);
40 }
41 
42 
43 /** Parses command line arguments and validates state */
parse_args()44 static void parse_args() {
45     int ch;
46     struct stat st;
47     while ((ch = getopt(argc, argv, "hu:")) != -1) {
48         switch (ch) {
49         case 'h':
50             show_help();
51             break;
52         case 'u':
53             unix_socket_name = strdup(optarg);
54             if (stat(unix_socket_name, &st) < 0) {
55                 fprintf(stderr, "Cannot access %s: %s\n", unix_socket_name, strerror(errno));
56                 exit(1);
57             }
58             break;
59         }
60     }
61     if (stat(unix_socket_name, &st) < 0 || access(unix_socket_name, R_OK) < 0) {
62         fprintf(stderr, "Cannot access %s: %s\n", unix_socket_name, strerror(errno));
63         exit(1);
64     }
65 }
66 
67 
68 /** Opens connection to the server */
open_connection()69 static void open_connection() {
70     int res;
71     char *msg;
72 
73     if ((res = sc_connect_unix(unix_socket_name, &sc, &msg)) != SC_OK) {
74         fprintf(stderr, "%s\n", msg);
75         free(msg);
76         exit(1);
77     }
78 
79     printf("Diagnostic/debugging/testing client for %s\n", SC_VER_SIG);
80     printf("Copyright (c) 2006. Ivan Voras <ivoras@gmail.com>\n");
81 }
82 
83 
cmd_ver()84 void cmd_ver() {
85     char sig[20];
86     if (sc_get_ver(&sc, sig) != SC_OK) {
87         fprintf(stderr, "Error getting version\n");
88         exit(1);
89     }
90     printf("Server version signature: %s\n", sig);
91 }
92 
93 
cmd_help()94 void cmd_help() {
95     printf("Lines not beginning with \".\" are treated as server SQL commands\n");
96     printf("and will be passed as such to sqlcached. Lines beginning with \".\"\n");
97     printf("should contain one of these commands:\n");
98     printf("   .ver     Show server version signature\n");
99     printf("   .help    Show this help\n");
100     printf("   .quit    Quit this client application\n");
101 }
102 
103 
cmd_quit()104 void cmd_quit() {
105     printf("Quitting\n");
106     exit(0);
107 }
108 
109 
do_sql(char * sql)110 void do_sql(char *sql) {
111     int res, i, j;
112     char *msg;
113     struct sc_result_set rs;
114 
115     if ((res = sc_exec_query(&sc, sql, &rs, &msg)) != SC_OK) {
116         fprintf(stderr, "error: %s\n", msg);
117         return;
118     }
119 
120     if (rs.n_rows > 0) {
121         int ccols = 0;
122 
123         for (i = 0; i < rs.n_cols; i++)
124             ccols += printf("|%s", rs.names[i]);
125         printf("\n");
126 
127         for (i = 0; i < ccols; i++)
128             printf("-");
129         printf("\n");
130 
131         for (i = 0; i < rs.n_rows; i++) {
132             for (j = 0; j < rs.n_cols; j++)
133                 printf("|%s", rs.rows[i][j]);
134             printf("\n");
135         }
136     }
137 
138     printf("%d row(s).\n", rs.n_rows);
139     sc_free_result(&sc, &rs);
140 }
141 
142 
143 /** Client loop */
client_loop()144 void client_loop() {
145     int done = 0;
146     char *line;
147 
148     while (!done) {
149         line = readline("sqlcached> ");
150         if (line == NULL) {
151             printf("\n");
152             break;
153         }
154         if (strlen(line) != 0) {
155             if (line[0] != '.') { /* treat it as sql */
156                 do_sql(line);
157             } else { /* special/internal command */
158                 char *cmd, *param;
159                 cmd = strtok(line, whitespace);
160                 if (strcmp(cmd, ".ver") == 0)
161                     cmd_ver();
162                 else if (strcmp(cmd, ".help") == 0)
163                     cmd_help();
164                 else if (strcmp(cmd, ".quit") == 0)
165                     cmd_quit();
166                 else {
167                     param = strtok(NULL, whitespace);
168                     printf("Huh?\n");
169                 }
170             }
171             add_history(line);
172         }
173         free(line);
174     }
175 
176 }
177 
178 
179 /** main() */
main(int _argc,char ** _argv)180 int main(int _argc, char **_argv) {
181     argc = _argc;
182     argv = _argv;
183     parse_args();
184     open_connection();
185     client_loop();
186     return 0;
187 }
188 
189