]> git.evergreen-ils.org Git - Evergreen.git/blob - OpenSRF/src/srfsh/srfsh.c
added the md5 server (opensrf.version)
[Evergreen.git] / OpenSRF / src / srfsh / srfsh.c
1 #include "srfsh.h"
2
3 int is_from_script = 0;
4 FILE* shell_writer = NULL;
5 FILE* shell_reader = NULL;
6
7 int main( int argc, char* argv[] ) {
8
9         /* --------------------------------------------- */
10         /* see if they have a .srfsh.xml in their home directory */
11         char* home = getenv("HOME");
12         int l = strlen(home) + 36;
13         char fbuf[l];
14         memset(fbuf, 0, l);
15         sprintf(fbuf,"%s/.srfsh.xml",home);
16
17         if(!access(fbuf, R_OK)) {
18                 if( ! osrf_system_bootstrap_client(fbuf, "srfsh") ) 
19                         fatal_handler( "Unable to bootstrap client for requests");
20
21         } else {
22                 fatal_handler( "No Config file found at %s", fbuf );
23         }
24
25         if(argc > 1) {
26                 /* for now.. the first arg is used as a script file for processing */
27                 int f;
28                 if( (f = open(argv[1], O_RDONLY)) == -1 )
29                         fatal_handler("Unable to open file %s for reading, exiting...", argv[1]);
30
31                 if(dup2(f, STDIN_FILENO) == -1)
32                         fatal_handler("Unable to duplicate STDIN, exiting...");
33
34                 close(f);
35                 is_from_script = 1;
36         }
37                 
38         /* --------------------------------------------- */
39         load_history();
40
41
42         client = osrf_system_get_transport_client();
43
44         /* open the shell handle */
45         shell_writer = popen( "bash", "w");
46         //shell_reader = popen( "bash", "r");
47
48         /* main process loop */
49         char* request;
50         while((request=readline(prompt))) {
51
52                 if( !strcmp(request, "exit") || !strcmp(request,"quit")) 
53                         break; 
54
55                 char* req_copy = strdup(request);
56
57                 parse_request( req_copy ); 
58                 if( request && strlen(request) > 1 ) {
59                         add_history(request);
60                 }
61
62                 free(request);
63                 free(req_copy);
64
65                 fflush(shell_writer);
66                 fflush(stderr);
67                 fflush(stdout);
68         }
69
70         if(history_file != NULL )
71                 write_history(history_file);
72
73         free(request);
74
75         osrf_system_shutdown();
76         return 0;
77 }
78
79 void sig_child_handler( int s ) {
80         child_dead = 1;
81 }
82
83 /*
84 void sig_int_handler( int s ) {
85         printf("\n");
86         caught_sigint = 1;
87         signal(SIGINT,sig_int_handler);
88 }
89 */
90
91 int load_history() {
92
93         char* home = getenv("HOME");
94         int l = strlen(home) + 24;
95         char fbuf[l];
96
97         memset(fbuf, 0, l);
98         sprintf(fbuf,"%s/.srfsh_history",home);
99         history_file = strdup(fbuf);
100
101         if(!access(history_file, W_OK | R_OK )) {
102                 history_length = 999;
103                 read_history(history_file);
104         }
105         return 1;
106 }
107
108
109 int parse_error( char* words[] ) {
110
111         if( ! words )
112                 return 0;
113
114
115         int i = 0;
116         char* current;
117         char buffer[256];
118         memset(buffer, 0, 256);
119         while( (current=words[i++]) ) {
120                 strcat(buffer, current);
121                 strcat(buffer, " ");
122         }
123         if( ! buffer || strlen(buffer) < 1 ) 
124                 printf("\n");
125
126         fprintf( stderr, "???: %s\n", buffer );
127         return 0;
128
129 }
130
131
132 int parse_request( char* request ) {
133
134         if( request == NULL )
135                 return 0;
136
137         int ret_val = 0;
138         int i = 0;
139         char* words[COMMAND_BUFSIZE]; 
140         memset(words,0,COMMAND_BUFSIZE);
141         char* req = request;
142
143         char* cur_tok = strtok( req, " " );
144
145         if( cur_tok == NULL )
146                 return 0;
147
148         while(cur_tok != NULL) {
149                 words[i++] = cur_tok;
150                 cur_tok = strtok( NULL, " " );
151         }
152
153
154         // not sure why (strtok?), but this is necessary
155         memset( words + i, 0, COMMAND_BUFSIZE - i );
156
157         /* pass off to the top level command */
158         if( !strcmp(words[0],"router") ) 
159                 ret_val = handle_router( words );
160
161         else if( !strcmp(words[0],"time") ) 
162                 ret_val = handle_time( words );
163
164         else if (!strcmp(words[0],"request"))
165                 ret_val = handle_request( words, 0 );
166
167         else if (!strcmp(words[0],"relay"))
168                 ret_val = handle_request( words, 1 );
169
170         else if (!strcmp(words[0],"help"))
171                 ret_val = print_help();
172
173         else if (!strcmp(words[0],"set"))
174                 ret_val = handle_set(words);
175
176         else if (!strcmp(words[0],"print"))
177                 ret_val = handle_print(words);
178
179         else if (!strcmp(words[0],"math_bench"))
180                 ret_val = handle_math(words);
181
182         else if (!strcmp(words[0],"introspect"))
183                 ret_val = handle_introspect(words);
184
185         else if (!strcmp(words[0],"login"))
186                 ret_val = handle_login(words);
187
188         else if (words[0][0] == '!')
189                 ret_val = handle_exec( words, 1 );
190
191         if(!ret_val) {
192                 #ifdef EXEC_DEFAULT
193                         return handle_exec( words, 0 );
194                 #else
195                         return parse_error( words );
196                 #endif
197         }
198
199         return 1;
200
201 }
202
203
204 int handle_introspect(char* words[]) {
205
206         if(words[1] && words[2]) {
207                 fprintf(stderr, "--> %s\n", words[1]);
208                 char buf[256];
209                 memset(buf,0,256);
210                 sprintf( buf, "request %s opensrf.system.method %s", words[1], words[2] );
211                 return parse_request( buf );
212
213         } else {
214         
215                 if(words[1]) {
216                         fprintf(stderr, "--> %s\n", words[1]);
217                         char buf[256];
218                         memset(buf,0,256);
219                         sprintf( buf, "request %s opensrf.system.method.all", words[1] );
220                         return parse_request( buf );
221                 }
222         }
223
224         return 0;
225 }
226
227
228 int handle_login( char* words[]) {
229
230         if( words[1] && words[2]) {
231
232                 char* username = words[1];
233                 char* password = words[2];
234
235                 char buf[256];
236                 memset(buf,0,256);
237
238                 char buf2[256];
239                 memset(buf2,0,256);
240
241                 sprintf( buf, 
242                                 "request open-ils.auth open-ils.auth.authenticate.init \"%s\"", username );
243                 parse_request(buf); 
244
245                 char* hash;
246                 if(last_result && last_result->_result_content) {
247                         jsonObject* r = last_result->_result_content;
248                         hash = jsonObjectGetString(r);
249                 } else return 0;
250
251
252                 char* pass_buf = md5sum(password);
253
254                 char both_buf[256];
255                 memset(both_buf,0,256);
256                 sprintf(both_buf,"%s%s",hash, pass_buf);
257
258                 char* mess_buf = md5sum(both_buf);
259
260                 sprintf( buf2,
261                                 "request open-ils.auth open-ils.auth.authenticate.complete \"%s\", \"%s\", \"opac\"", 
262                                 username, mess_buf );
263
264                 free(pass_buf);
265                 free(mess_buf);
266
267                 parse_request( buf2 );
268
269                 char* x = jsonObjectGetString(last_result->_result_content);
270                 if(x) login_session = strdup(x);
271                 else login_session = NULL;
272
273                 printf("Login Session: %s\n", login_session );
274                 
275                 return 1;
276
277         }
278
279         return 0;
280 }
281
282 int handle_set( char* words[]) {
283
284         char* variable;
285         if( (variable=words[1]) ) {
286
287                 char* val;
288                 if( (val=words[2]) ) {
289
290                         if(!strcmp(variable,"pretty_print")) {
291                                 if(!strcmp(val,"true")) {
292                                         pretty_print = 1;
293                                         printf("pretty_print = true\n");
294                                         return 1;
295                                 } 
296                                 if(!strcmp(val,"false")) {
297                                         pretty_print = 0;
298                                         printf("pretty_print = false\n");
299                                         return 1;
300                                 } 
301                         }
302
303                         if(!strcmp(variable,"raw_print")) {
304                                 if(!strcmp(val,"true")) {
305                                         raw_print = 1;
306                                         printf("raw_print = true\n");
307                                         return 1;
308                                 } 
309                                 if(!strcmp(val,"false")) {
310                                         raw_print = 0;
311                                         printf("raw_print = false\n");
312                                         return 1;
313                                 } 
314                         }
315
316                 }
317         }
318
319         return 0;
320 }
321
322
323 int handle_print( char* words[]) {
324
325         char* variable;
326         if( (variable=words[1]) ) {
327                 if(!strcmp(variable,"pretty_print")) {
328                         if(pretty_print) {
329                                 printf("pretty_print = true\n");
330                                 return 1;
331                         } else {
332                                 printf("pretty_print = false\n");
333                                 return 1;
334                         }
335                 }
336
337                 if(!strcmp(variable,"login")) {
338                         printf("login session = %s\n", login_session );
339                         return 1;
340                 }
341
342         }
343         return 0;
344 }
345
346 int handle_router( char* words[] ) {
347
348         if(!client)
349                 return 1;
350
351         int i;
352
353         if( words[1] ) { 
354                 if( !strcmp(words[1],"query") ) {
355                         
356                         if( words[2] && !strcmp(words[2],"servers") ) {
357                                 for(i=3; i < COMMAND_BUFSIZE - 3 && words[i]; i++ ) {   
358                                         router_query_servers( words[i] );
359                                 }
360                                 return 1;
361                         }
362                         return 0;
363                 }
364                 return 0;
365         }
366         return 0;
367 }
368
369
370 /* if new shell, spawn a new child and subshell to do the work,
371         otherwise pipe the request to the currently open (piped) shell */
372 int handle_exec(char* words[], int new_shell) {
373
374         if(!words[0]) return 0;
375
376         if( words[0] && words[0][0] == '!') {
377                 int len = strlen(words[0]);
378                 char command[len];
379                 memset(command,0,len);
380         
381                 int i; /* chop out the ! */
382                 for( i=1; i!= len; i++) {
383                         command[i-1] = words[0][i];
384                 }
385         
386                 free(words[0]);
387                 words[0] = strdup(command);
388         }
389
390         if(new_shell) {
391                 signal(SIGCHLD, sig_child_handler);
392
393                 if(fork()) {
394         
395                         waitpid(-1, 0, 0);
396                         if(child_dead) {
397                                 signal(SIGCHLD,sig_child_handler);
398                                 child_dead = 0;
399                         }
400         
401                 } else {
402                         execvp( words[0], words );
403                         exit(0);
404                 }
405
406         } else {
407
408
409                 growing_buffer* b = buffer_init(64);
410                 int i = 0;
411                 while(words[i]) 
412                         buffer_fadd( b, "%s ", words[i++] );
413         
414                 buffer_add( b, "\n");
415         
416                 //int reader;
417                 //int reader = dup2(STDOUT_FILENO, reader);
418                 //int reader = dup(STDOUT_FILENO);
419                 //close(STDOUT_FILENO);
420
421                 fprintf( shell_writer, b->buf );
422                 buffer_free(b);
423         
424                 fflush(shell_writer);
425                 usleep(1000);
426
427                 /*
428                 char c[4096];
429                 bzero(c, 4096);
430                 read( reader, c, 4095 );
431                 fprintf(stderr, "read %s", c);
432                 dup2(reader, STDOUT_FILENO);
433                 */
434
435         }
436
437         
438         return 1;
439 }
440
441
442 int handle_request( char* words[], int relay ) {
443
444         if(!client)
445                 return 1;
446
447         if(words[1]) {
448                 char* server = words[1];
449                 char* method = words[2];
450                 int i;
451                 growing_buffer* buffer = NULL;
452                 if(!relay) {
453                         buffer = buffer_init(128);
454                         buffer_add(buffer, "[");
455                         for(i = 3; words[i] != NULL; i++ ) {
456                                 /* removes trailing semicolon if user accidentally enters it */
457                                 if( words[i][strlen(words[i])-1] == ';' )
458                                         words[i][strlen(words[i])-1] = '\0';
459                                 buffer_add( buffer, words[i] );
460                                 buffer_add(buffer, " ");
461                         }
462                         buffer_add(buffer, "]");
463                 }
464
465                 return send_request( server, method, buffer, relay );
466         } 
467
468         return 0;
469 }
470
471 int send_request( char* server, 
472                 char* method, growing_buffer* buffer, int relay ) {
473         if( server == NULL || method == NULL )
474                 return 0;
475
476         jsonObject* params = NULL;
477         if( !relay ) {
478                 if( buffer != NULL && buffer->n_used > 0 ) 
479                         params = json_parse_string(buffer->buf);
480         } else {
481                 if(!last_result || ! last_result->_result_content) { 
482                         printf("We're not going to call 'relay' with no result params\n");
483                         return 1;
484                 }
485                 else {
486                         jsonObject* o = jsonNewObject(NULL);
487                         jsonObjectPush(o, last_result->_result_content );
488                         params = o;
489                 }
490         }
491
492
493         if(buffer->n_used > 0 && params == NULL) {
494                 fprintf(stderr, "JSON error detected, not executing\n");
495                 return 1;
496         }
497
498         osrf_app_session* session = osrf_app_client_session_init(server);
499
500         if(!osrf_app_session_connect(session)) {
501                 warning_handler( "Unable to connect to remote service %s\n", server );
502                 return 1;
503         }
504
505         double start = get_timestamp_millis();
506         //int req_id = osrf_app_session_make_request( session, params, method, 1, NULL );
507         int req_id = osrf_app_session_make_req( session, params, method, 1, NULL );
508
509
510         osrf_message* omsg = osrf_app_session_request_recv( session, req_id, 60 );
511
512         if(!omsg) 
513                 printf("\nReceived no data from server\n");
514         
515         
516         signal(SIGPIPE, SIG_IGN);
517
518         FILE* less; 
519         if(!is_from_script) less = popen( "less -EX", "w");
520         else less = stdout;
521
522         if( less == NULL ) { less = stdout; }
523
524         growing_buffer* resp_buffer = buffer_init(4096);
525
526         while(omsg) {
527
528                 if(raw_print) {
529
530                         if(omsg->_result_content) {
531         
532                                 osrf_message_free(last_result);
533                                 last_result = omsg;
534         
535                                 char* content;
536         
537                                 if( pretty_print && omsg->_result_content ) {
538                                         char* j = jsonObjectToJSON(omsg->_result_content);
539                                         //content = json_printer(j); 
540                                         content = jsonFormatString(j);
541                                         free(j);
542                                 } else
543                                         content = jsonObjectGetString(omsg->_result_content);
544         
545                                 printf( "\nReceived Data: %s\n", content ); 
546                                 free(content);
547         
548                         } else {
549
550                                 char code[16];
551                                 memset(code, 0, 16);
552                                 sprintf( code, "%d", omsg->status_code );
553                                 buffer_add( resp_buffer, code );
554
555                                 printf( "\nReceived Exception:\nName: %s\nStatus: %s\nStatus: %s\n", 
556                                                 omsg->status_name, omsg->status_text, code );
557
558                                 fflush(stdout);
559                         }
560
561                 } else {
562
563                         if(omsg->_result_content) {
564         
565                                 osrf_message_free(last_result);
566                                 last_result = omsg;
567         
568                                 char* content;
569         
570                                 if( pretty_print && omsg->_result_content ) {
571                                         char* j = jsonObjectToJSON(omsg->_result_content);
572                                         //content = json_printer(j); 
573                                         content = jsonFormatString(j);
574                                         free(j);
575                                 } else
576                                         content = jsonObjectGetString(omsg->_result_content);
577         
578                                 buffer_add( resp_buffer, "\nReceived Data: " ); 
579                                 buffer_add( resp_buffer, content );
580                                 buffer_add( resp_buffer, "\n" );
581                                 free(content);
582         
583                         } else {
584         
585                                 buffer_add( resp_buffer, "\nReceived Exception:\nName: " );
586                                 buffer_add( resp_buffer, omsg->status_name );
587                                 buffer_add( resp_buffer, "\nStatus: " );
588                                 buffer_add( resp_buffer, omsg->status_text );
589                                 buffer_add( resp_buffer, "\nStatus: " );
590                                 char code[16];
591                                 memset(code, 0, 16);
592                                 sprintf( code, "%d", omsg->status_code );
593                                 buffer_add( resp_buffer, code );
594                         }
595                 }
596
597
598                 omsg = osrf_app_session_request_recv( session, req_id, 5 );
599
600         }
601
602         double end = get_timestamp_millis();
603
604         fprintf( less, resp_buffer->buf );
605         buffer_free( resp_buffer );
606         fprintf( less, "\n------------------------------------\n");
607         if( osrf_app_session_request_complete( session, req_id ))
608                 fprintf(less, "Request Completed Successfully\n");
609
610
611         fprintf(less, "Request Time in seconds: %.3f\n", end - start );
612         fprintf(less, "------------------------------------\n");
613
614         pclose(less); 
615
616         osrf_app_session_request_finish( session, req_id );
617         osrf_app_session_disconnect( session );
618         osrf_app_session_destroy( session );
619
620
621         return 1;
622
623
624 }
625
626 int handle_time( char* words[] ) {
627
628         if( ! words[1] ) {
629
630                 char buf[36];
631                 memset(buf,0,36);
632                 get_timestamp(buf);
633                 printf( "%s\n", buf );
634                 return 1;
635         }
636
637         if( words[1] ) {
638                 time_t epoch = (time_t)atoi( words[1] );
639                 char* localtime = strdup( ctime( &epoch ) );
640                 printf( "%s => %s", words[1], localtime );
641                 free(localtime);
642                 return 1;
643         }
644
645         return 0;
646
647 }
648
649                 
650
651 int router_query_servers( char* router_server ) {
652
653         if( ! router_server || strlen(router_server) == 0 ) 
654                 return 0;
655
656         char rbuf[256];
657         memset(rbuf,0,256);
658         sprintf(rbuf,"router@%s/router", router_server );
659                 
660         transport_message* send = 
661                 message_init( "servers", NULL, NULL, rbuf, NULL );
662         message_set_router_info( send, NULL, NULL, NULL, "query", 0 );
663
664         client_send_message( client, send );
665         message_free( send );
666
667         transport_message* recv = client_recv( client, -1 );
668         if( recv == NULL ) {
669                 fprintf(stderr, "NULL message received from router\n");
670                 return 1;
671         }
672         
673         printf( 
674                         "---------------------------------------------------------------------------------\n"
675                         "Received from 'server' query on %s\n"
676                         "---------------------------------------------------------------------------------\n"
677                         "original reg time | latest reg time | last used time | class | server\n"
678                         "---------------------------------------------------------------------------------\n"
679                         "%s"
680                         "---------------------------------------------------------------------------------\n"
681                         , router_server, recv->body );
682
683         message_free( recv );
684         
685         return 1;
686 }
687                 
688 int print_help() {
689
690         printf(
691                         "---------------------------------------------------------------------------------\n"
692                         "Commands:\n"
693                         "---------------------------------------------------------------------------------\n"
694                         "help                   - Display this message\n"
695                         "!<command> [args] - Forks and runs the given command in the shell\n"
696                         "time                   - Prints the current time\n"                                    
697                         "time <timestamp>       - Formats seconds since epoch into readable format\n"   
698                         "set <variable> <value> - set a srfsh variable (e.g. set pretty_print true )\n"
699                         "print <variable>               - Displays the value of a srfsh variable\n"
700                         "---------------------------------------------------------------------------------\n"
701
702                         "router query servers <server1 [, server2, ...]>\n"
703                         "       - Returns stats on connected services\n"
704                         "\n"
705                         "\n"
706                         "request <service> <method> [ <json formatted string of params> ]\n"
707                         "       - Anything passed in will be wrapped in a json array,\n"
708                         "               so add commas if there is more than one param\n"
709                         "\n"
710                         "\n"
711                         "relay <service> <method>\n"
712                         "       - Performs the requested query using the last received result as the param\n"
713                         "\n"
714                         "\n"
715                         "math_bench <num_batches> [0|1|2]\n"
716                         "       - 0 means don't reconnect, 1 means reconnect after each batch of 4, and\n"
717                         "                2 means reconnect after every request\n"
718                         "\n"
719                         "introspect <service>\n"
720                         "       - prints the API for the service\n"
721                         "\n"
722                         "\n"
723                         "---------------------------------------------------------------------------------\n"
724                         " Commands for Open-ILS\n"
725                         "---------------------------------------------------------------------------------\n"
726                         "login <username> <password>\n"
727                         "       -       Logs into the 'server' and displays the session id\n"
728                         "       - To view the session id later, enter: print login\n"
729                         "---------------------------------------------------------------------------------\n"
730                         "\n"
731                         "\n"
732                         "Note: long output is piped through 'less'.  To search in 'less', type: /<search>\n"
733                         "---------------------------------------------------------------------------------\n"
734                         "\n"
735                         );
736
737         return 1;
738 }
739
740
741
742 char* tabs(int count) {
743         growing_buffer* buf = buffer_init(24);
744         int i;
745         for(i=0;i!=count;i++)
746                 buffer_add(buf, "  ");
747
748         char* final = buffer_data( buf );
749         buffer_free( buf );
750         return final;
751 }
752
753 int handle_math( char* words[] ) {
754         if( words[1] && words[2] ) 
755                 return do_math( atoi(words[1]), atoi(words[2]) );
756         return 0;
757 }
758
759
760 int do_math( int count, int style ) {
761
762         osrf_app_session* session = osrf_app_client_session_init(  "opensrf.math" );
763
764         jsonObject* params = json_parse_string("[]");
765         jsonObjectPush(params,jsonNewObject("1"));
766         jsonObjectPush(params,jsonNewObject("2"));
767
768         char* methods[] = { "add", "sub", "mult", "div" };
769         char* answers[] = { "3", "-1", "2", "0.500000" };
770
771         float times[ count * 4 ];
772         memset(times,0,count*4);
773
774         int k;
775         for(k=0;k!=100;k++) {
776                 if(!(k%10)) 
777                         fprintf(stderr,"|");
778                 else
779                         fprintf(stderr,".");
780         }
781
782         fprintf(stderr,"\n\n");
783
784         int running = 0;
785         int i;
786         for(i=0; i!= count; i++) {
787
788                 int j;
789                 for(j=0; j != 4; j++) {
790
791                         ++running;
792                         struct timeb t1;
793                         struct timeb t2;
794
795                         ftime(&t1);
796                         //int req_id = osrf_app_session_make_request( session, params, methods[j], 1, NULL );
797                         int req_id = osrf_app_session_make_req( session, params, methods[j], 1, NULL );
798
799                         osrf_message* omsg = osrf_app_session_request_recv( session, req_id, 5 );
800
801
802                         ftime(&t2);
803
804                         double start    = ( (int)t1.time        + ( ((float)t1.millitm) / 1000 ) );
805                         double end              = ( (int)t2.time        + ( ((float)t2.millitm) / 1000 ) );
806
807                         times[(4*i) + j] = end - start;
808
809                         if(omsg) {
810         
811                                 if(omsg->_result_content) {
812                                         char* jsn = jsonObjectToJSON(omsg->_result_content);
813                                         if(!strcmp(jsn, answers[j]))
814                                                 fprintf(stderr, "+");
815                                         else
816                                                 fprintf(stderr, "\n![%s] - should be %s\n", jsn, answers[j] );
817                                         free(jsn);
818                                 }
819
820
821                                 osrf_message_free(omsg);
822                 
823                         } else { fprintf( stderr, "\nempty message for tt: %d\n", req_id ); }
824
825                         osrf_app_session_request_finish( session, req_id );
826
827                         if(style == 2)
828                                 osrf_app_session_disconnect( session );
829
830                         if(!(running%100))
831                                 fprintf(stderr,"\n");
832                 }
833
834                 if(style==1)
835                         osrf_app_session_disconnect( session );
836         }
837
838         osrf_app_session_destroy( session );
839         jsonObjectFree(params);
840
841         int c;
842         float total = 0;
843         for(c=0; c!= count*4; c++) 
844                 total += times[c];
845
846         float avg = total / (count*4); 
847         fprintf(stderr, "\n      Average round trip time: %f\n", avg );
848
849         return 1;
850 }