1 | /***************************************
2 | $Revision: 1.24 $
3 |
4 | Protocol config module (pc). This is the protocol that the admin uses to
5 | talk to the server.
6 |
7 | Status: NOT REVUED, NOT TESTED
8 |
9 | ******************/ /******************
10 | Filename : protocol_config.c
11 | Authors : ottrey@ripe.net
12 | marek@ripe.net
13 | To Do : Add a facility to take callbacks instead of
14 | hard-coding menu options.
15 | Add in all the menu support provided by the GLib
16 | libraries.
17 | (Remove strtok if multiple threads are to be used.)
18 | use gnu readline with expansion and history
19 | ******************/ /******************
20 | Copyright (c) 1999 RIPE NCC
21 |
22 | All Rights Reserved
23 |
24 | Permission to use, copy, modify, and distribute this software and its
25 | documentation for any purpose and without fee is hereby granted,
26 | provided that the above copyright notice appear in all copies and that
27 | both that copyright notice and this permission notice appear in
28 | supporting documentation, and that the name of the author not be
29 | used in advertising or publicity pertaining to distribution of the
30 | software without specific, written prior permission.
31 |
32 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
33 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
34 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
35 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
36 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38 | ***************************************/
39 | #include <stdio.h>
40 | #include <stdlib.h>
41 | /*** solaris' header file doesn't contain the crypt definition...
42 | #include <unistd.h> */
43 |
44 | extern char* crypt(const char *, const char *); /* crypt stuff */
45 | #include <time.h> /* Time stuff */
46 | #include <sys/ioctl.h> /* Terminal control stuff */
47 | #include <termio.h> /* Terminal control stuff */
48 |
49 | #include "mysql_driver.h"
50 | #include "constants.h"
51 | #include "properties.h"
52 | #include "thread.h"
53 | #include "protocol_config.h"
54 | #include "access_control.h"
55 | #include "socket.h"
56 | #include "ta.h"
57 |
58 | /*+ Each command has a +*/
59 | typedef struct _command {
60 | const char *name; /*+ Name to be invoked. +*/
61 | char *(*function)(char *, sk_conn_st *); /*+ Function to be invoked. +*/
62 | const char *help; /*+ Command help. +*/
63 | } Command;
64 |
65 | /*
66 | * Forward declarations
67 | */
68 | static char *command_help(char *input, sk_conn_st *condat);
69 | static char *command_quit(char *input, sk_conn_st *condat);
70 | static char *command_show(char *input, sk_conn_st *condat);
71 | static char *command_repeat(char *input, sk_conn_st *condat);
72 | static char *show_const(char *input, sk_conn_st *condat);
73 | static char *show_consts(char *input, sk_conn_st *condat);
74 | static char *show_props(char *input, sk_conn_st *condat);
75 | static char *show_threads(char *input, sk_conn_st *condat);
76 | static char *show_whois(char *input, sk_conn_st *condat);
77 | static char *show_access(char *input, sk_conn_st *condat);
78 | static char *show_acl(char *input, sk_conn_st *condat);
79 | static char *command_set(char *input, sk_conn_st *condat);
80 | static char *set_const(char *input, sk_conn_st *condat);
81 | static char *set_consts(char *input, sk_conn_st *condat);
82 | static char *set_props(char *input, sk_conn_st *condat);
83 | static char *command_sql(char *input, sk_conn_st *condat);
84 | static char *command_purify(char *input, sk_conn_st *condat);
85 | static char *set_acl(char *input, sk_conn_st *condat);
86 |
87 | /*+
88 | * Contains the command definitions
89 | +*/
90 |
91 | extern void purify_new_inuse(void);
92 |
93 | static struct _command command[] = {
94 | {"help" , command_help , HELP_HELP },
95 | {"quit" , command_quit , HELP_QUIT },
96 | {"show" , command_show , HELP_SHOW },
97 | {"repeat" , command_repeat , HELP_REPEAT },
98 | {"set" , command_set , HELP_SET },
99 | {"sql" , command_sql , HELP_SQL },
100 | {"purify" , command_purify , "trigger a new memory-in-use report" },
101 | {NULL , NULL , NULL }
102 | };
103 |
104 | /*+
105 | * Contains the show commands
106 | +*/
107 | static struct _command show[] = {
108 | {"const" , show_const , HELP_SHOW_CONST },
109 | {"consts" , show_consts , HELP_SHOW_CONSTS },
110 | {"props" , show_props , HELP_SHOW_PROPS },
111 | {"threads" , show_threads , HELP_SHOW_THREAD },
112 | {"whois" , show_whois , HELP_SHOW_WHOIS },
113 | {"access" , show_access , HELP_SHOW_ACCESS },
114 | {"acl" , show_acl , HELP_SHOW_ACL },
115 | {NULL , NULL , NULL }
116 | };
117 |
118 | /*+
119 | * Contains the set commands
120 | +*/
121 | static struct _command set[] = {
122 | {"const" , set_const , HELP_SET_CONST },
123 | {"consts" , set_consts , HELP_SET_CONSTS },
124 | {"props" , set_props , HELP_SET_PROPS },
125 | {"acl" , set_acl , HELP_SET_ACL },
126 | {NULL , NULL , NULL }
127 | };
128 |
129 | static int find_command(char *comm_name, Command *comm) {
130 | int i, index;
131 | char comm_buffer[STR_L];
132 |
133 | if (comm_name != NULL) {
134 | strcpy(comm_buffer, comm_name);
135 | strtok(comm_buffer, " \t");
136 | for (i=0, index=-1; comm[i].name != NULL; i++) {
137 | if ( strcmp(comm_buffer, comm[i].name) == 0) {
138 | index = i;
139 | break;
140 | }
141 | }
142 | }
143 | else {
144 | index = -2;
145 | }
146 |
147 | return index;
148 | } /* find_command() */
149 |
150 | static char *show_commands(Command *comm) {
151 | char *str;
152 | char help_buffer[STR_XL];
153 | char help_comm[STR_M];
154 | int i;
155 |
156 | sprintf(help_buffer, " commands are:\n\n");
157 | i = 0;
158 | while (comm[i].name != NULL) {
159 | sprintf(help_comm, "%s\t%s\n", comm[i].name, comm[i].help);
160 | strcat(help_buffer, help_comm);
161 | i++;
162 | }
163 |
164 | /* str = (char *)calloc(1, strlen(help_buffer)+1); */
165 | dieif( wr_malloc((void **)&str, strlen(help_buffer)+1) != UT_OK);
166 | strcpy(str, help_buffer);
167 |
168 | return str;
169 | } /* show_commands() */
170 |
171 |
172 | /*
173 | * Command functions
174 | */
175 |
176 | static char *command_purify(char *input, sk_conn_st *condat)
177 | {
178 | char *str;
179 | dieif( wr_malloc((void **)&str, 4) != UT_OK);
180 | #if 0
181 | purify_new_inuse();
182 | strcpy(str, "OK");
183 | #else
184 | strcpy(str, "NOP");
185 | #endif
186 |
187 | return str;
188 | }
189 |
190 | static char *command_help(char *input, sk_conn_st *condat) {
191 | char *str;
192 | char *str1;
193 | char output_buffer[STR_XXL];
194 | char *command_name;
195 | int index;
196 |
197 | strcpy(output_buffer, "");
198 |
199 | strtok(input, " \t");
200 | command_name = (char *)strtok(NULL, " \t");
201 |
202 | index = find_command(command_name, command);
203 |
204 | switch (index) {
205 | case -2:
206 | strcat(output_buffer, "Main");
207 | str1 = show_commands(command);
208 | strcat(output_buffer, str1);
209 | wr_free(str1);
210 | break;
211 |
212 | case -1:
213 | strcat(output_buffer, HELP_ERROR);
214 | strcat(output_buffer, command_name);
215 | break;
216 |
217 | default:
218 | strcat(output_buffer, command[index].help);
219 | }
220 |
221 | /*
222 | str = (char *)CopyString(output_buffer);
223 | */
224 | /* str = (char *)calloc(1, strlen(output_buffer)+1); */
225 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
226 | strcpy(str, output_buffer);
227 |
228 | return str;
229 | } /* command_help() */
230 |
231 | static char *command_quit(char *input, sk_conn_st *condat) {
232 | /* Administrator wishes to quit. */
233 | return NULL;
234 | } /* command_quit() */
235 |
236 | static char *show_const(char *input, sk_conn_st *condat) {
237 | /* Administrator wishes to show constants. */
238 | char *result;
239 | char *name;
240 | char *tmp_input;
241 |
242 | /* tmp_input = (char *)calloc(1, strlen(input)+1); */
243 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
244 | strcpy(tmp_input, input);
245 |
246 | /* The name will be the third token in stuff */
247 | strtok(tmp_input, " ");
248 | strtok(NULL, " ");
249 | name = (char *)strtok(NULL, " ");
250 |
251 | result = CO_const_to_string(name);
252 |
253 | wr_free(tmp_input);
254 | return result;
255 |
256 | } /* show_const() */
257 |
258 | static char *show_consts(char *input, sk_conn_st *condat) {
259 | /* Administrator wishes to show constants. */
260 | return CO_to_string();
261 |
262 | } /* show_consts() */
263 |
264 | static char *show_props(char *input, sk_conn_st *condat) {
265 | /* Administrator wishes to show properties. */
266 | return PR_to_string();
267 |
268 | } /* show_props() */
269 |
270 | static char *show_threads(char *input, sk_conn_st *condat) {
271 | /* Administrator wishes to show thread information. */
272 | return TA_tostring();
273 |
274 | } /* show_thread() */
275 |
276 | static char *show_whois(char *input, sk_conn_st *condat) {
277 | /* Administrator wishes to show whois query information. */
278 | return wr_string("WQ_to_string();");
279 |
280 | } /* show_whois() */
281 |
282 | static char *show_access(char *input, sk_conn_st *condat) {
283 | /* Administrator wishes to show whois query information. */
284 |
285 | char line[128];
286 | int cnt;
287 | er_ret_t err;
288 |
289 | if( act_runtime->top_ptr != NULL ) {
290 | char *header = AC_to_string_header();
291 |
292 | /* print header */
293 | SK_cd_puts(condat,header);
294 | wr_free(header);
295 |
296 | cnt = rx_walk_tree(act_runtime->top_ptr, AC_rxwalkhook_print,
297 | RX_WALK_SKPGLU, /* print no glue nodes */
298 | 255, 0, 0, condat, &err);
299 | sprintf(line,"Found %d nodes\n", cnt);
300 | SK_cd_puts(condat,line);
301 | }
302 |
303 | return wr_string("");
304 |
305 | } /* show_access() */
306 |
307 | static char *show_acl(char *input, sk_conn_st *condat) {
308 | /* Administrator wishes to show access control list. */
309 |
310 | char line[128];
311 | int cnt;
312 | er_ret_t err;
313 |
314 | if( act_acl->top_ptr != NULL ) {
315 | char *header = AC_acl_to_string_header();
316 |
317 | /* print header */
318 | SK_cd_puts(condat,header);
319 | wr_free(header);
320 |
321 | cnt = rx_walk_tree(act_acl->top_ptr, AC_rxwalkhook_print_acl,
322 | RX_WALK_SKPGLU, /* print no glue nodes */
323 | 255, 0, 0, condat, &err);
324 | sprintf(line,"Found %d nodes\n", cnt);
325 | SK_cd_puts(condat,line);
326 | }
327 |
328 | return wr_string("");
329 |
330 | } /* show_acl() */
331 |
332 | static char *command_execute(char *input, char *comm_name,
333 | Command *comm, sk_conn_st *condat) {
334 | char *str;
335 | char *str1;
336 | char output_buffer[STR_XXL];
337 | char *name;
338 | int index;
339 | char *tmp_input;
340 |
341 | /* Make a copy of the input */
342 | /* tmp_input = (char *)calloc(1, strlen(input)+1); */
343 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
344 | strcpy(tmp_input, input);
345 |
346 | strtok(tmp_input, " \t");
347 | name = (char *)strtok(NULL, " \t");
348 |
349 | index = find_command(name, comm);
350 |
351 | switch (index) {
352 | case -2:
353 | str1 = show_commands(comm);
354 | sprintf(output_buffer, "%s%s", comm_name, str1);
355 | wr_free(str1);
356 | break;
357 |
358 | case -1:
359 | sprintf(output_buffer, "%s invalid command: %s", comm_name, name);
360 | break;
361 |
362 | default:
363 | sprintf(output_buffer, "%s", comm[index].function(input, condat));
364 | }
365 |
366 | /*
367 | str = (char *)CopyString(output_buffer);
368 | */
369 | /* str = (char *)calloc(1, strlen(output_buffer)+1); */
370 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
371 | strcpy(str, output_buffer);
372 |
373 | wr_free(tmp_input);
374 |
375 | return str;
376 | } /* command_execute() */
377 |
378 | static char *command_show(char *input, sk_conn_st *condat) {
379 | return command_execute(input, "Show", show, condat);
380 | } /* command_show() */
381 |
382 | static char *command_repeat(char *input, sk_conn_st *condat) {
383 | char *command_ptr;
384 |
385 | /* Goto the bit after "repeat n " */
386 | for (command_ptr=input+7; command_ptr[0] != ' ' || (command_ptr[0] >= '0' && command_ptr[0] <= '9'); command_ptr++);
387 |
388 | return command_ptr+1;
389 |
390 | } /* command_show() */
391 |
392 | static char *set_const(char *input, sk_conn_st *condat) {
393 | /* Administrator wishes to set a constant. */
394 | char *result;
395 | char result_buf[STR_M];
396 | char *tmp_input;
397 | char *name;
398 | char *value;
399 | int value_len;
400 | char *stuff;
401 | char *str;
402 |
403 | /* tmp_input = (char *)calloc(1, strlen(input)+1); */
404 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
405 | strcpy(tmp_input, input);
406 |
407 | stuff = (char *)strtok(tmp_input, "=");
408 |
409 | /* The value will be after the '=' */
410 | value = (char *)strtok(NULL, "=");
411 |
412 | /* The name will be the third token in stuff */
413 | strtok(stuff, " ");
414 | strtok(NULL, " ");
415 | name = (char *)strtok(NULL, " ");
416 |
417 | /* Remove any quotes */
418 | if (value[0] == '"') {
419 | value++;
420 | }
421 | value_len=strlen(value);
422 | if (value[value_len-1] == '"') {
423 | value[value_len-1]='\0';
424 | }
425 |
426 | printf("set_const name=(%s), value=(%s)\n", name, value);
427 | if (CO_set_const(name, value) == 0) {
428 | strcpy(result_buf, "Constant successfully set\n");
429 | }
430 | else {
431 | str = CO_const_to_string(name);
432 | sprintf(result_buf, "Constant not successfully set\nReverting to: %s=%s\n", name, str);
433 | wr_free(str);
434 | }
435 |
436 | /* result = (char *)calloc(1, strlen(result_buf)+1); */
437 | dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
438 | strcpy(result, result_buf);
439 |
440 | wr_free(tmp_input);
441 | return result;
442 | } /* set_const() */
443 |
444 | static char *set_consts(char *input, sk_conn_st *condat) {
445 | /* Administrator wishes to set constants. */
446 | return CO_set();
447 | } /* set_consts() */
448 |
449 | static char *set_props(char *input, sk_conn_st *condat) {
450 | /* Administrator wishes to set properties. */
451 | return PR_set();
452 | } /* set_props() */
453 |
454 | static char *set_acl(char *input, sk_conn_st *condat) {
455 |
456 | /* first 8 characters are "set acl " so skip them */
457 |
458 | if( ! NOERR( AC_asc_acl_command_set( input+8, "Manual"))) {
459 | return wr_string("Error\n");
460 | }
461 | else {
462 | return wr_string("OK");
463 | }
464 | }
465 |
466 | static char *command_set(char *input, sk_conn_st *condat) {
467 | return command_execute(input, "Set", set, condat);
468 | } /* command_set() */
469 |
470 | static char *command_sql(char *input, sk_conn_st *condat) {
471 | char *str;
472 | char output_buffer[STR_XXL];
473 | char *sql_str;
474 |
475 | char *res=NULL;
476 |
477 | SQ_result_set_t *sql_result=NULL;
478 | SQ_connection_t *sql_connection;
479 |
480 | sql_connection = SQ_get_connection("",0,"","","");
481 |
482 | if (sql_connection == NULL) {
483 | printf("/* Check for errors */\n");
484 | }
485 |
486 | /* skip over the "sql" */
487 | sql_str = input+3;
488 | /* skip over white space */
489 | while (sql_str[0] == ' ') {
490 | sql_str++;
491 | }
492 |
493 | strcpy(output_buffer, "");
494 |
495 | if (sql_connection != NULL) {
496 | if (strcmp(sql_str, "status") == 0) {
497 | /* Get the status of the database */
498 | res = SQ_info_to_string(sql_connection);
499 | }
500 | else {
501 | if (strcmp(sql_str, "") == 0) {
502 | /* Execute the default query (from the properties file) */
503 | SQ_execute_query(sql_connection, "", &sql_result);
504 | }
505 | else {
506 | /* Execute an sql query */
507 | SQ_execute_query(sql_connection, sql_str, &sql_result);
508 | }
509 | if (sql_result != NULL) {
510 | res = SQ_result_to_string(sql_result);
511 | }
512 | else {
513 | printf("no results\n");
514 | }
515 | }
516 | if (res != NULL) {
517 | sprintf(output_buffer, "%s", res);
518 | }
519 | else {
520 | printf("empty results\n");
521 | }
522 | }
523 | else {
524 | printf("Failed to make connection\n");
525 | }
526 |
527 | /*
528 | strcat(output_buffer, mysql_info(sql_connection));
529 | */
530 |
531 | strcat(output_buffer, "XXX Results from mysql_info(sql_connection) is meant to go here. But it's not working!");
532 |
533 | /*
534 | str = (char *)CopyString(output_buffer);
535 | */
536 | /* str = (char *)calloc(1, strlen(output_buffer)+1); */
537 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
538 | strcpy(str, output_buffer);
539 |
540 | wr_free(res);
541 | SQ_free_result(sql_result);
542 |
543 | SQ_close_connection(sql_connection);
544 |
545 | return str;
546 |
547 | } /* command_sql() */
548 |
549 |
550 | /* process_input() */
551 | /*++++++++++++++++++++++++++++++++++++++
552 |
553 | Process the input.
554 |
555 | sk_conn_st *condat connection data
556 |
557 | More:
558 | +html+ <PRE>
559 | Author:
560 | ottrey
561 | +html+ </PRE>
562 | ++++++++++++++++++++++++++++++++++++++*/
563 | static int process_input(char *input, sk_conn_st *condat) {
564 | int connected = 1;
565 | char *input_ptr;
566 | char *output;
567 | int index;
568 | int repeat=0;
569 |
570 | input_ptr = input;
571 |
572 | if (strncmp(input, "repeat", 6) == 0) {
573 | /* XXX This is a really dodgy call, that hopefully converts
574 | the string to the value of the first found integer. */
575 | repeat = atoi(input+7);
576 | input_ptr= command_repeat(input, condat);
577 | }
578 |
579 | index = find_command(input_ptr, command);
580 |
581 | do {
582 | switch (index) {
583 | case -1:
584 | /* Command not found */
585 | output = command_help(NULL, condat);
586 | break;
587 |
588 | default:
589 | output = command[index].function(input_ptr, condat);
590 | }
591 |
592 | if(output == NULL) {
593 | connected = 0;
594 | } else {
595 | /*
596 | printf("thread output=\n%s\n", output);
597 | */
598 | if ( CO_get_clear_screen() == 1 ) {
599 | SK_cd_puts(condat, CLEAR_SCREEN);
600 | }
601 | SK_cd_puts(condat, output);
602 | SK_cd_puts(condat, "\n");
603 | SK_cd_puts(condat, CO_get_prompt());
604 |
605 | wr_free(output);
606 | }
607 |
608 | if (repeat > 0) {
609 | repeat--;
610 | }
611 |
612 | } while (repeat > 0);
613 |
614 | return connected;
615 |
616 | } /* process_input() */
617 |
618 | static void log_config(const char *user, const char *status) {
619 | FILE *logf;
620 | time_t now;
621 | char timebuf[26];
622 |
623 | time(&now);
624 |
625 | printf(LOG_CONFIG, TH_get_id(), user, status, ctime_r(&now, timebuf));
626 |
627 | } /* log_config() */
628 |
629 | /* XXX Doh! These only change the server's terminal. We need some
630 | tricky escape sequence to send over the socket.
631 | static void echo_off(int sock) {
632 | struct termio state;
633 |
634 | ioctl(0, TIOCGETP, &state);
635 | state.c_lflag &= ~ECHO;
636 | ioctl(0, TIOCSETP, &state);
637 | } echo_off() */
638 |
639 | /* XXX Doh! These only change the server's terminal. We need some
640 | tricky escape sequence to send over the socket.
641 | static void echo_on(int sock) {
642 | struct termio state;
643 |
644 | ioctl(0, TIOCGETP, &state);
645 | state.c_lflag |= ECHO;
646 | ioctl(0, TIOCSETP, &state);
647 | } echo_on() */
648 |
649 | static char *authenticate_user(sk_conn_st *condat) {
650 | char *user = NULL;
651 | const char Salt[2] = "DB";
652 | char input[MAX_INPUT_SIZE];
653 | int read_result;
654 | char *password=NULL;
655 | char *user_password=NULL;
656 | char user_buf[10];
657 |
658 | SK_cd_puts(condat, LOGIN_PROMPT);
659 | read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
660 |
661 | strncpy(user_buf, input, 10);
662 |
663 | SK_cd_puts(condat, PASSWD_PROMPT);
664 | /* XXX These aren't working.
665 | SK_puts(sock, ECHO_ON);
666 | echo_off(sock);
667 | */
668 | read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
669 | /* XXX These aren't working.
670 | echo_on(sock);
671 | SK_puts(sock, ECHO_OFF);
672 | */
673 |
674 | password = crypt(input, Salt);
675 |
676 | user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);
677 |
678 | if (user_password != NULL) {
679 | if (strcmp(password, user_password) == 0) {
680 | /*user = (char *)calloc(1, strlen(user_buf)+1);*/
681 | dieif( wr_malloc((void **)&user, strlen(user_buf)+1) != UT_OK);
682 | strcpy(user, user_buf);
683 | }
684 | }
685 |
686 | if (user == NULL) {
687 | log_config(user_buf, "unsuccesful login attempt");
688 | }
689 |
690 | return user;
691 |
692 | } /* authenticate_user() */
693 |
694 | void PC_interact(int sock) {
695 | char input[MAX_INPUT_SIZE];
696 | int connected = 1;
697 | char *user=NULL;
698 | sk_conn_st condat;
699 |
700 | memset( &condat, 0, sizeof(condat));
701 | condat.sock = sock;
702 | SK_getpeerip(sock, &(condat.rIP));
703 | condat.ip = SK_getpeername(sock); /* XXX *alloc involved */
704 |
705 | /* Welcome the client */
706 | SK_cd_puts(&condat, CO_get_welcome());
707 |
708 | /* Authenticate the user */
709 | if (CO_get_authenticate() == 1) {
710 | user = authenticate_user(&condat);
711 | }
712 | else {
713 | user="nobody";
714 | }
715 |
716 | if (user != NULL) {
717 |
718 |
719 | /* Log admin logging on */
720 | log_config(user, "logged on");
721 |
722 |
723 | {
724 | char timestring[26];
725 | extern time_t SV_starttime;
726 |
727 | ctime_r(&SV_starttime, timestring);
728 | SK_cd_printf(&condat,
729 | "System running since %sUptime in seconds: %ld \n\n",
730 | timestring,
731 | time(NULL) - SV_starttime);
732 | }
733 |
734 | SK_cd_puts(&condat, CO_get_prompt());
735 |
736 | while (condat.rtc==0 && connected) {
737 | char *ichr;
738 | char *icopy;
739 | char *chr;
740 | /* Read input */
741 | SK_cd_gets(&condat, input, MAX_INPUT_SIZE);
742 |
743 | /* filter junk out: leading/trailing whitespaces */
744 |
745 | /* 1. advance to non-whitespace */
746 | for(ichr=input; *ichr != 0 && isspace(*ichr); ichr++) {
747 | /* EMPTY */
748 | }
749 | /* 2. copy the rest (even if empty) */
750 | dieif( (icopy = strdup(ichr)) == NULL);
751 |
752 | /* 3. chop trailing spaces */
753 | for( chr = icopy + strlen(icopy)-1 ;
754 | chr != icopy && isspace(*chr);
755 | chr--) {
756 | *chr = 0;
757 | }
758 |
759 | /* set thread accounting */
760 | TA_setactivity(icopy);
761 | TA_increment();
762 |
763 | connected = process_input(icopy, &condat);
764 |
765 | TA_setactivity("");
766 |
767 | free(icopy);
768 | }
769 |
770 | /* Log admin logging off */
771 | log_config(user, "logged off");
772 | }
773 |
774 | /* Close the socket */
775 | SK_close(sock);
776 |
777 | wr_free(condat.ip);
778 | } /* PC_interact() */
779 |