1 | /***************************************
2 | $Revision: 1.21 $
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 *set_ban(char *input, sk_conn_st *condat);
85 |
86 | /*+
87 | * Contains the command definitions
88 | +*/
89 | static struct _command command[] = {
90 | {"help" , command_help , HELP_HELP },
91 | {"quit" , command_quit , HELP_QUIT },
92 | {"show" , command_show , HELP_SHOW },
93 | {"repeat" , command_repeat , HELP_REPEAT },
94 | {"set" , command_set , HELP_SET },
95 | {"sql" , command_sql , HELP_SQL },
96 | {NULL , NULL , NULL }
97 | };
98 |
99 | /*+
100 | * Contains the show commands
101 | +*/
102 | static struct _command show[] = {
103 | {"const" , show_const , HELP_SHOW_CONST },
104 | {"consts" , show_consts , HELP_SHOW_CONSTS },
105 | {"props" , show_props , HELP_SHOW_PROPS },
106 | {"threads" , show_threads , HELP_SHOW_THREAD },
107 | {"whois" , show_whois , HELP_SHOW_WHOIS },
108 | {"access" , show_access , HELP_SHOW_ACCESS },
109 | {"acl" , show_acl , HELP_SHOW_ACL },
110 | {NULL , NULL , NULL }
111 | };
112 |
113 | /*+
114 | * Contains the set commands
115 | +*/
116 | static struct _command set[] = {
117 | {"const" , set_const , HELP_SET_CONST },
118 | {"consts" , set_consts , HELP_SET_CONSTS },
119 | {"props" , set_props , HELP_SET_PROPS },
120 | {"ban" , set_ban , HELP_SET_BAN },
121 | {NULL , NULL , NULL }
122 | };
123 |
124 | static int find_command(char *comm_name, Command *comm) {
125 | int i, index;
126 | char comm_buffer[STR_L];
127 |
128 | if (comm_name != NULL) {
129 | strcpy(comm_buffer, comm_name);
130 | strtok(comm_buffer, " \t");
131 | for (i=0, index=-1; comm[i].name != NULL; i++) {
132 | if ( strcmp(comm_buffer, comm[i].name) == 0) {
133 | index = i;
134 | break;
135 | }
136 | }
137 | }
138 | else {
139 | index = -2;
140 | }
141 |
142 | return index;
143 | } /* find_command() */
144 |
145 | static char *show_commands(Command *comm) {
146 | char *str;
147 | char help_buffer[STR_XL];
148 | char help_comm[STR_M];
149 | int i;
150 |
151 | sprintf(help_buffer, " commands are:\n\n");
152 | i = 0;
153 | while (comm[i].name != NULL) {
154 | sprintf(help_comm, "%s\t%s\n", comm[i].name, comm[i].help);
155 | strcat(help_buffer, help_comm);
156 | i++;
157 | }
158 |
159 | /* str = (char *)calloc(1, strlen(help_buffer)+1); */
160 | dieif( wr_malloc((void **)&str, strlen(help_buffer)+1) != UT_OK);
161 | strcpy(str, help_buffer);
162 |
163 | return str;
164 | } /* show_commands() */
165 |
166 |
167 | /*
168 | * Command functions
169 | */
170 | static char *command_help(char *input, sk_conn_st *condat) {
171 | char *str;
172 | char *str1;
173 | char output_buffer[STR_XXL];
174 | char *command_name;
175 | int index;
176 |
177 | strcpy(output_buffer, "");
178 |
179 | strtok(input, " \t");
180 | command_name = (char *)strtok(NULL, " \t");
181 |
182 | index = find_command(command_name, command);
183 |
184 | switch (index) {
185 | case -2:
186 | strcat(output_buffer, "Main");
187 | str1 = show_commands(command);
188 | strcat(output_buffer, str1);
189 | wr_free(str1);
190 | break;
191 |
192 | case -1:
193 | strcat(output_buffer, HELP_ERROR);
194 | strcat(output_buffer, command_name);
195 | break;
196 |
197 | default:
198 | strcat(output_buffer, command[index].help);
199 | }
200 |
201 | /*
202 | str = (char *)CopyString(output_buffer);
203 | */
204 | /* str = (char *)calloc(1, strlen(output_buffer)+1); */
205 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
206 | strcpy(str, output_buffer);
207 |
208 | return str;
209 | } /* command_help() */
210 |
211 | static char *command_quit(char *input, sk_conn_st *condat) {
212 | /* Administrator wishes to quit. */
213 | return NULL;
214 | } /* command_quit() */
215 |
216 | static char *show_const(char *input, sk_conn_st *condat) {
217 | /* Administrator wishes to show constants. */
218 | char *result;
219 | char *name;
220 | char *tmp_input;
221 |
222 | /* tmp_input = (char *)calloc(1, strlen(input)+1); */
223 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
224 | strcpy(tmp_input, input);
225 |
226 | /* The name will be the third token in stuff */
227 | strtok(tmp_input, " ");
228 | strtok(NULL, " ");
229 | name = (char *)strtok(NULL, " ");
230 |
231 | result = CO_const_to_string(name);
232 |
233 | wr_free(tmp_input);
234 | return result;
235 |
236 | } /* show_const() */
237 |
238 | static char *show_consts(char *input, sk_conn_st *condat) {
239 | /* Administrator wishes to show constants. */
240 | return CO_to_string();
241 |
242 | } /* show_consts() */
243 |
244 | static char *show_props(char *input, sk_conn_st *condat) {
245 | /* Administrator wishes to show properties. */
246 | return PR_to_string();
247 |
248 | } /* show_props() */
249 |
250 | static char *show_threads(char *input, sk_conn_st *condat) {
251 | /* Administrator wishes to show thread information. */
252 | return TA_tostring();
253 |
254 | } /* show_thread() */
255 |
256 | static char *show_whois(char *input, sk_conn_st *condat) {
257 | /* Administrator wishes to show whois query information. */
258 | return wr_string("WQ_to_string();");
259 |
260 | } /* show_whois() */
261 |
262 | static char *show_access(char *input, sk_conn_st *condat) {
263 | /* Administrator wishes to show whois query information. */
264 |
265 | char line[128];
266 | int cnt;
267 | er_ret_t err;
268 |
269 | if( act_runtime->top_ptr != NULL ) {
270 | char *header = AC_to_string_header();
271 |
272 | /* print header */
273 | SK_cd_puts(condat,header);
274 | wr_free(header);
275 |
276 | cnt = rx_walk_tree(act_runtime->top_ptr, AC_rxwalkhook_print,
277 | RX_WALK_SKPGLU, /* print no glue nodes */
278 | 255, 0, 0, condat, &err);
279 | sprintf(line,"Found %d nodes\n", cnt);
280 | SK_cd_puts(condat,line);
281 | }
282 |
283 | return wr_string("");
284 |
285 | } /* show_access() */
286 |
287 | static char *show_acl(char *input, sk_conn_st *condat) {
288 | /* Administrator wishes to show access control list. */
289 |
290 | char line[128];
291 | int cnt;
292 | er_ret_t err;
293 |
294 | if( act_acl->top_ptr != NULL ) {
295 | char *header = AC_acl_to_string_header();
296 |
297 | /* print header */
298 | SK_cd_puts(condat,header);
299 | wr_free(header);
300 |
301 | cnt = rx_walk_tree(act_acl->top_ptr, AC_rxwalkhook_print_acl,
302 | RX_WALK_SKPGLU, /* print no glue nodes */
303 | 255, 0, 0, condat, &err);
304 | sprintf(line,"Found %d nodes\n", cnt);
305 | SK_cd_puts(condat,line);
306 | }
307 |
308 | return wr_string("");
309 |
310 | } /* show_acl() */
311 |
312 | static char *command_execute(char *input, char *comm_name,
313 | Command *comm, sk_conn_st *condat) {
314 | char *str;
315 | char *str1;
316 | char output_buffer[STR_XXL];
317 | char *name;
318 | int index;
319 | char *tmp_input;
320 |
321 | /* Make a copy of the input */
322 | /* tmp_input = (char *)calloc(1, strlen(input)+1); */
323 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
324 | strcpy(tmp_input, input);
325 |
326 | strtok(tmp_input, " \t");
327 | name = (char *)strtok(NULL, " \t");
328 |
329 | index = find_command(name, comm);
330 |
331 | switch (index) {
332 | case -2:
333 | str1 = show_commands(comm);
334 | sprintf(output_buffer, "%s%s", comm_name, str1);
335 | wr_free(str1);
336 | break;
337 |
338 | case -1:
339 | sprintf(output_buffer, "%s invalid command: %s", comm_name, name);
340 | break;
341 |
342 | default:
343 | sprintf(output_buffer, "%s", comm[index].function(input, condat));
344 | }
345 |
346 | /*
347 | str = (char *)CopyString(output_buffer);
348 | */
349 | /* str = (char *)calloc(1, strlen(output_buffer)+1); */
350 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
351 | strcpy(str, output_buffer);
352 |
353 | wr_free(tmp_input);
354 |
355 | return str;
356 | } /* command_execute() */
357 |
358 | static char *command_show(char *input, sk_conn_st *condat) {
359 | return command_execute(input, "Show", show, condat);
360 | } /* command_show() */
361 |
362 | static char *command_repeat(char *input, sk_conn_st *condat) {
363 | char *command_ptr;
364 |
365 | /* Goto the bit after "repeat n " */
366 | for (command_ptr=input+7; command_ptr[0] != ' ' || (command_ptr[0] >= '0' && command_ptr[0] <= '9'); command_ptr++);
367 |
368 | return command_ptr+1;
369 |
370 | } /* command_show() */
371 |
372 | static char *set_const(char *input, sk_conn_st *condat) {
373 | /* Administrator wishes to set a constant. */
374 | char *result;
375 | char result_buf[STR_M];
376 | char *tmp_input;
377 | char *name;
378 | char *value;
379 | int value_len;
380 | char *stuff;
381 | char *str;
382 |
383 | /* tmp_input = (char *)calloc(1, strlen(input)+1); */
384 | dieif( wr_malloc((void **)&tmp_input, strlen(input)+1) != UT_OK);
385 | strcpy(tmp_input, input);
386 |
387 | stuff = (char *)strtok(tmp_input, "=");
388 |
389 | /* The value will be after the '=' */
390 | value = (char *)strtok(NULL, "=");
391 |
392 | /* The name will be the third token in stuff */
393 | strtok(stuff, " ");
394 | strtok(NULL, " ");
395 | name = (char *)strtok(NULL, " ");
396 |
397 | /* Remove any quotes */
398 | if (value[0] == '"') {
399 | value++;
400 | }
401 | value_len=strlen(value);
402 | if (value[value_len-1] == '"') {
403 | value[value_len-1]='\0';
404 | }
405 |
406 | printf("set_const name=(%s), value=(%s)\n", name, value);
407 | if (CO_set_const(name, value) == 0) {
408 | strcpy(result_buf, "Constant successfully set\n");
409 | }
410 | else {
411 | str = CO_const_to_string(name);
412 | sprintf(result_buf, "Constant not successfully set\nReverting to: %s=%s\n", name, str);
413 | wr_free(str);
414 | }
415 |
416 | /* result = (char *)calloc(1, strlen(result_buf)+1); */
417 | dieif( wr_malloc((void **)&result, strlen(result_buf)+1) != UT_OK);
418 | strcpy(result, result_buf);
419 |
420 | wr_free(tmp_input);
421 | return result;
422 | } /* set_const() */
423 |
424 | static char *set_consts(char *input, sk_conn_st *condat) {
425 | /* Administrator wishes to set constants. */
426 | return CO_set();
427 | } /* set_consts() */
428 |
429 | static char *set_props(char *input, sk_conn_st *condat) {
430 | /* Administrator wishes to set properties. */
431 | return PR_set();
432 | } /* set_props() */
433 |
434 | static char *set_ban(char *input, sk_conn_st *condat) {
435 | int flag;
436 | char addrstr[128];
437 |
438 | if( sscanf(input,"set ban %d %127s", &flag, addrstr) < 2) {
439 | return wr_string("Invalid arguments");
440 | }
441 | else {
442 | if( ! NOERR( AC_asc_ban_set( addrstr, "Manual", (flag!=0) ))) {
443 | return wr_string("Error\n");
444 | }
445 | else {
446 | return wr_string("OK");
447 | }
448 | }
449 | }
450 |
451 | static char *command_set(char *input, sk_conn_st *condat) {
452 | return command_execute(input, "Set", set, condat);
453 | } /* command_set() */
454 |
455 | static char *command_sql(char *input, sk_conn_st *condat) {
456 | char *str;
457 | char output_buffer[STR_XXL];
458 | char *sql_str;
459 |
460 | char *res=NULL;
461 |
462 | SQ_result_set_t *sql_result=NULL;
463 | SQ_connection_t *sql_connection;
464 |
465 | sql_connection = SQ_get_connection(CO_get_host(), CO_get_database_port(), CO_get_database(), CO_get_user(), CO_get_password() );
466 |
467 | if (sql_connection == NULL) {
468 | printf("/* Check for errors */\n");
469 | }
470 |
471 | /* skip over the "sql" */
472 | sql_str = input+3;
473 | /* skip over white space */
474 | while (sql_str[0] == ' ') {
475 | sql_str++;
476 | }
477 |
478 | strcpy(output_buffer, "");
479 |
480 | if (sql_connection != NULL) {
481 | if (strcmp(sql_str, "status") == 0) {
482 | /* Get the status of the database */
483 | res = SQ_info_to_string(sql_connection);
484 | }
485 | else {
486 | if (strcmp(sql_str, "") == 0) {
487 | /* Execute the default query (from the properties file) */
488 | SQ_execute_query(sql_connection, CO_get_query(), &sql_result);
489 | }
490 | else {
491 | /* Execute an sql query */
492 | SQ_execute_query(sql_connection, sql_str, &sql_result);
493 | }
494 | if (sql_result != NULL) {
495 | res = SQ_result_to_string(sql_result);
496 | }
497 | else {
498 | printf("no results\n");
499 | }
500 | }
501 | if (res != NULL) {
502 | sprintf(output_buffer, "%s", res);
503 | }
504 | else {
505 | printf("empty results\n");
506 | }
507 | }
508 | else {
509 | printf("Failed to make connection\n");
510 | }
511 |
512 | /*
513 | strcat(output_buffer, mysql_info(sql_connection));
514 | */
515 |
516 | strcat(output_buffer, "XXX Results from mysql_info(sql_connection) is meant to go here. But it's not working!");
517 |
518 | /*
519 | str = (char *)CopyString(output_buffer);
520 | */
521 | /* str = (char *)calloc(1, strlen(output_buffer)+1); */
522 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
523 | strcpy(str, output_buffer);
524 |
525 | wr_free(res);
526 | SQ_free_result(sql_result);
527 |
528 | SQ_close_connection(sql_connection);
529 |
530 | return str;
531 |
532 | } /* command_sql() */
533 |
534 |
535 | /* process_input() */
536 | /*++++++++++++++++++++++++++++++++++++++
537 |
538 | Process the input.
539 |
540 | sk_conn_st *condat connection data
541 |
542 | More:
543 | +html+ <PRE>
544 | Author:
545 | ottrey
546 | +html+ </PRE>
547 | ++++++++++++++++++++++++++++++++++++++*/
548 | static int process_input(char *input, sk_conn_st *condat) {
549 | int connected = 1;
550 | char *input_ptr;
551 | char *output;
552 | int index;
553 | int repeat=0;
554 |
555 | input_ptr = input;
556 |
557 | if (strncmp(input, "repeat", 6) == 0) {
558 | /* XXX This is a really dodgy call, that hopefully converts
559 | the string to the value of the first found integer. */
560 | repeat = atoi(input+7);
561 | input_ptr= command_repeat(input, condat);
562 | }
563 |
564 | index = find_command(input_ptr, command);
565 |
566 | do {
567 | switch (index) {
568 | case -1:
569 | /* Command not found */
570 | output = command_help(NULL, condat);
571 | break;
572 |
573 | default:
574 | output = command[index].function(input_ptr, condat);
575 | }
576 |
577 | if(output == NULL) {
578 | connected = 0;
579 | } else {
580 | /*
581 | printf("thread output=\n%s\n", output);
582 | */
583 | if ( CO_get_clear_screen() == 1 ) {
584 | SK_cd_puts(condat, CLEAR_SCREEN);
585 | }
586 | SK_cd_puts(condat, output);
587 | SK_cd_puts(condat, "\n");
588 | SK_cd_puts(condat, CO_get_prompt());
589 |
590 | wr_free(output);
591 | }
592 |
593 | if (repeat > 0) {
594 | repeat--;
595 | sleep(CO_get_sleep_time());
596 | }
597 |
598 | } while (repeat > 0);
599 |
600 | return connected;
601 |
602 | } /* process_input() */
603 |
604 | static void log_config(const char *user, const char *status) {
605 | FILE *logf;
606 | time_t now;
607 | char timebuf[26];
608 |
609 | time(&now);
610 |
611 | if (CO_get_config_logging() == 1) {
612 |
613 | if (strcmp(CO_get_config_logfile(), "stdout") == 0) {
614 | printf(LOG_CONFIG, TH_get_id(), user, status, ctime_r(&now, timebuf));
615 | }
616 | else {
617 | logf = fopen(CO_get_config_logfile(), "a");
618 | fprintf(logf, LOG_CONFIG, TH_get_id(), user, status, ctime_r(&now, timebuf));
619 | fclose(logf);
620 | }
621 | }
622 |
623 | } /* log_config() */
624 |
625 | /* XXX Doh! These only change the server's terminal. We need some
626 | tricky escape sequence to send over the socket.
627 | static void echo_off(int sock) {
628 | struct termio state;
629 |
630 | ioctl(0, TIOCGETP, &state);
631 | state.c_lflag &= ~ECHO;
632 | ioctl(0, TIOCSETP, &state);
633 | } echo_off() */
634 |
635 | /* XXX Doh! These only change the server's terminal. We need some
636 | tricky escape sequence to send over the socket.
637 | static void echo_on(int sock) {
638 | struct termio state;
639 |
640 | ioctl(0, TIOCGETP, &state);
641 | state.c_lflag |= ECHO;
642 | ioctl(0, TIOCSETP, &state);
643 | } echo_on() */
644 |
645 | static char *authenticate_user(sk_conn_st *condat) {
646 | char *user = NULL;
647 | const char Salt[2] = "DB";
648 | char input[MAX_INPUT_SIZE];
649 | int read_result;
650 | char *password=NULL;
651 | char *user_password=NULL;
652 | char user_buf[10];
653 |
654 | SK_cd_puts(condat, LOGIN_PROMPT);
655 | read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
656 |
657 | strncpy(user_buf, input, 10);
658 |
659 | SK_cd_puts(condat, PASSWD_PROMPT);
660 | /* XXX These aren't working.
661 | SK_puts(sock, ECHO_ON);
662 | echo_off(sock);
663 | */
664 | read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
665 | /* XXX These aren't working.
666 | echo_on(sock);
667 | SK_puts(sock, ECHO_OFF);
668 | */
669 |
670 | password = crypt(input, Salt);
671 |
672 | user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);
673 |
674 | if (user_password != NULL) {
675 | if (strcmp(password, user_password) == 0) {
676 | /*user = (char *)calloc(1, strlen(user_buf)+1);*/
677 | dieif( wr_malloc((void **)&user, strlen(user_buf)+1) != UT_OK);
678 | strcpy(user, user_buf);
679 | }
680 | }
681 |
682 | if (user == NULL) {
683 | log_config(user_buf, "unsuccesful login attempt");
684 | }
685 |
686 | return user;
687 |
688 | } /* authenticate_user() */
689 |
690 | void PC_interact(int sock) {
691 | char input[MAX_INPUT_SIZE];
692 | int connected = 1;
693 | char *user=NULL;
694 | sk_conn_st condat;
695 |
696 | memset( &condat, 0, sizeof(condat));
697 | condat.sock = sock;
698 | SK_getpeerip(sock, &(condat.rIP));
699 | condat.ip = SK_getpeername(sock); /* XXX *alloc involved */
700 |
701 | /* Welcome the client */
702 | SK_cd_puts(&condat, CO_get_welcome());
703 |
704 | /* Authenticate the user */
705 | if (CO_get_authenticate() == 1) {
706 | user = authenticate_user(&condat);
707 | }
708 | else {
709 | user="nobody";
710 | }
711 |
712 | if (user != NULL) {
713 |
714 |
715 | /* Log admin logging on */
716 | log_config(user, "logged on");
717 |
718 |
719 | {
720 | char timestring[26];
721 | extern time_t SV_starttime;
722 |
723 | ctime_r(&SV_starttime, timestring);
724 | SK_cd_printf(&condat,
725 | "System running since %sUptime in seconds: %ld \n\n",
726 | timestring,
727 | time(NULL) - SV_starttime);
728 | }
729 |
730 | SK_cd_puts(&condat, CO_get_prompt());
731 |
732 | while (condat.rtc==0 && connected) {
733 | char *ichr;
734 | char *icopy;
735 | char *chr;
736 | /* Read input */
737 | SK_cd_gets(&condat, input, MAX_INPUT_SIZE);
738 |
739 | /* filter junk out: leading/trailing whitespaces */
740 |
741 | /* 1. advance to non-whitespace */
742 | for(ichr=input; *ichr != 0 && isspace(*ichr); ichr++) {
743 | /* EMPTY */
744 | }
745 | /* 2. copy the rest (even if empty) */
746 | dieif( (icopy = strdup(ichr)) == NULL);
747 |
748 | /* 3. chop trailing spaces */
749 | for( chr = icopy + strlen(icopy)-1 ;
750 | chr != icopy && isspace(*chr);
751 | chr--) {
752 | *chr = 0;
753 | }
754 |
755 | /* set thread accounting */
756 | TA_setactivity(icopy);
757 | TA_increment();
758 |
759 | connected = process_input(icopy, &condat);
760 |
761 | TA_setactivity("");
762 |
763 | free(icopy);
764 | }
765 |
766 | /* Log admin logging off */
767 | log_config(user, "logged off");
768 | }
769 |
770 | /* Close the socket */
771 | SK_close(sock);
772 |
773 | wr_free(condat.ip);
774 | } /* PC_interact() */
775 |