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