1 | /***************************************
2 | $Revision: 1.23 $
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_acl(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 | {"acl" , set_acl , HELP_SET_ACL },
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_acl(char *input, sk_conn_st *condat) {
435 |
436 | /* first 8 characters are "set acl " so skip them */
437 |
438 | if( ! NOERR( AC_asc_acl_command_set( input+8, "Manual"))) {
439 | return wr_string("Error\n");
440 | }
441 | else {
442 | return wr_string("OK");
443 | }
444 | }
445 |
446 | static char *command_set(char *input, sk_conn_st *condat) {
447 | return command_execute(input, "Set", set, condat);
448 | } /* command_set() */
449 |
450 | static char *command_sql(char *input, sk_conn_st *condat) {
451 | char *str;
452 | char output_buffer[STR_XXL];
453 | char *sql_str;
454 |
455 | char *res=NULL;
456 |
457 | SQ_result_set_t *sql_result=NULL;
458 | SQ_connection_t *sql_connection;
459 |
460 | sql_connection = SQ_get_connection("",0,"","","");
461 |
462 | if (sql_connection == NULL) {
463 | printf("/* Check for errors */\n");
464 | }
465 |
466 | /* skip over the "sql" */
467 | sql_str = input+3;
468 | /* skip over white space */
469 | while (sql_str[0] == ' ') {
470 | sql_str++;
471 | }
472 |
473 | strcpy(output_buffer, "");
474 |
475 | if (sql_connection != NULL) {
476 | if (strcmp(sql_str, "status") == 0) {
477 | /* Get the status of the database */
478 | res = SQ_info_to_string(sql_connection);
479 | }
480 | else {
481 | if (strcmp(sql_str, "") == 0) {
482 | /* Execute the default query (from the properties file) */
483 | SQ_execute_query(sql_connection, "", &sql_result);
484 | }
485 | else {
486 | /* Execute an sql query */
487 | SQ_execute_query(sql_connection, sql_str, &sql_result);
488 | }
489 | if (sql_result != NULL) {
490 | res = SQ_result_to_string(sql_result);
491 | }
492 | else {
493 | printf("no results\n");
494 | }
495 | }
496 | if (res != NULL) {
497 | sprintf(output_buffer, "%s", res);
498 | }
499 | else {
500 | printf("empty results\n");
501 | }
502 | }
503 | else {
504 | printf("Failed to make connection\n");
505 | }
506 |
507 | /*
508 | strcat(output_buffer, mysql_info(sql_connection));
509 | */
510 |
511 | strcat(output_buffer, "XXX Results from mysql_info(sql_connection) is meant to go here. But it's not working!");
512 |
513 | /*
514 | str = (char *)CopyString(output_buffer);
515 | */
516 | /* str = (char *)calloc(1, strlen(output_buffer)+1); */
517 | dieif( wr_malloc((void **)&str, strlen(output_buffer)+1) != UT_OK);
518 | strcpy(str, output_buffer);
519 |
520 | wr_free(res);
521 | SQ_free_result(sql_result);
522 |
523 | SQ_close_connection(sql_connection);
524 |
525 | return str;
526 |
527 | } /* command_sql() */
528 |
529 |
530 | /* process_input() */
531 | /*++++++++++++++++++++++++++++++++++++++
532 |
533 | Process the input.
534 |
535 | sk_conn_st *condat connection data
536 |
537 | More:
538 | +html+ <PRE>
539 | Author:
540 | ottrey
541 | +html+ </PRE>
542 | ++++++++++++++++++++++++++++++++++++++*/
543 | static int process_input(char *input, sk_conn_st *condat) {
544 | int connected = 1;
545 | char *input_ptr;
546 | char *output;
547 | int index;
548 | int repeat=0;
549 |
550 | input_ptr = input;
551 |
552 | if (strncmp(input, "repeat", 6) == 0) {
553 | /* XXX This is a really dodgy call, that hopefully converts
554 | the string to the value of the first found integer. */
555 | repeat = atoi(input+7);
556 | input_ptr= command_repeat(input, condat);
557 | }
558 |
559 | index = find_command(input_ptr, command);
560 |
561 | do {
562 | switch (index) {
563 | case -1:
564 | /* Command not found */
565 | output = command_help(NULL, condat);
566 | break;
567 |
568 | default:
569 | output = command[index].function(input_ptr, condat);
570 | }
571 |
572 | if(output == NULL) {
573 | connected = 0;
574 | } else {
575 | /*
576 | printf("thread output=\n%s\n", output);
577 | */
578 | if ( CO_get_clear_screen() == 1 ) {
579 | SK_cd_puts(condat, CLEAR_SCREEN);
580 | }
581 | SK_cd_puts(condat, output);
582 | SK_cd_puts(condat, "\n");
583 | SK_cd_puts(condat, CO_get_prompt());
584 |
585 | wr_free(output);
586 | }
587 |
588 | if (repeat > 0) {
589 | repeat--;
590 | }
591 |
592 | } while (repeat > 0);
593 |
594 | return connected;
595 |
596 | } /* process_input() */
597 |
598 | static void log_config(const char *user, const char *status) {
599 | FILE *logf;
600 | time_t now;
601 | char timebuf[26];
602 |
603 | time(&now);
604 |
605 | printf(LOG_CONFIG, TH_get_id(), user, status, ctime_r(&now, timebuf));
606 |
607 | } /* log_config() */
608 |
609 | /* XXX Doh! These only change the server's terminal. We need some
610 | tricky escape sequence to send over the socket.
611 | static void echo_off(int sock) {
612 | struct termio state;
613 |
614 | ioctl(0, TIOCGETP, &state);
615 | state.c_lflag &= ~ECHO;
616 | ioctl(0, TIOCSETP, &state);
617 | } echo_off() */
618 |
619 | /* XXX Doh! These only change the server's terminal. We need some
620 | tricky escape sequence to send over the socket.
621 | static void echo_on(int sock) {
622 | struct termio state;
623 |
624 | ioctl(0, TIOCGETP, &state);
625 | state.c_lflag |= ECHO;
626 | ioctl(0, TIOCSETP, &state);
627 | } echo_on() */
628 |
629 | static char *authenticate_user(sk_conn_st *condat) {
630 | char *user = NULL;
631 | const char Salt[2] = "DB";
632 | char input[MAX_INPUT_SIZE];
633 | int read_result;
634 | char *password=NULL;
635 | char *user_password=NULL;
636 | char user_buf[10];
637 |
638 | SK_cd_puts(condat, LOGIN_PROMPT);
639 | read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
640 |
641 | strncpy(user_buf, input, 10);
642 |
643 | SK_cd_puts(condat, PASSWD_PROMPT);
644 | /* XXX These aren't working.
645 | SK_puts(sock, ECHO_ON);
646 | echo_off(sock);
647 | */
648 | read_result = SK_cd_gets(condat, input, MAX_INPUT_SIZE);
649 | /* XXX These aren't working.
650 | echo_on(sock);
651 | SK_puts(sock, ECHO_OFF);
652 | */
653 |
654 | password = crypt(input, Salt);
655 |
656 | user_password = PR_get_property(user_buf, DEFAULT_USER_NAME);
657 |
658 | if (user_password != NULL) {
659 | if (strcmp(password, user_password) == 0) {
660 | /*user = (char *)calloc(1, strlen(user_buf)+1);*/
661 | dieif( wr_malloc((void **)&user, strlen(user_buf)+1) != UT_OK);
662 | strcpy(user, user_buf);
663 | }
664 | }
665 |
666 | if (user == NULL) {
667 | log_config(user_buf, "unsuccesful login attempt");
668 | }
669 |
670 | return user;
671 |
672 | } /* authenticate_user() */
673 |
674 | void PC_interact(int sock) {
675 | char input[MAX_INPUT_SIZE];
676 | int connected = 1;
677 | char *user=NULL;
678 | sk_conn_st condat;
679 |
680 | memset( &condat, 0, sizeof(condat));
681 | condat.sock = sock;
682 | SK_getpeerip(sock, &(condat.rIP));
683 | condat.ip = SK_getpeername(sock); /* XXX *alloc involved */
684 |
685 | /* Welcome the client */
686 | SK_cd_puts(&condat, CO_get_welcome());
687 |
688 | /* Authenticate the user */
689 | if (CO_get_authenticate() == 1) {
690 | user = authenticate_user(&condat);
691 | }
692 | else {
693 | user="nobody";
694 | }
695 |
696 | if (user != NULL) {
697 |
698 |
699 | /* Log admin logging on */
700 | log_config(user, "logged on");
701 |
702 |
703 | {
704 | char timestring[26];
705 | extern time_t SV_starttime;
706 |
707 | ctime_r(&SV_starttime, timestring);
708 | SK_cd_printf(&condat,
709 | "System running since %sUptime in seconds: %ld \n\n",
710 | timestring,
711 | time(NULL) - SV_starttime);
712 | }
713 |
714 | SK_cd_puts(&condat, CO_get_prompt());
715 |
716 | while (condat.rtc==0 && connected) {
717 | char *ichr;
718 | char *icopy;
719 | char *chr;
720 | /* Read input */
721 | SK_cd_gets(&condat, input, MAX_INPUT_SIZE);
722 |
723 | /* filter junk out: leading/trailing whitespaces */
724 |
725 | /* 1. advance to non-whitespace */
726 | for(ichr=input; *ichr != 0 && isspace(*ichr); ichr++) {
727 | /* EMPTY */
728 | }
729 | /* 2. copy the rest (even if empty) */
730 | dieif( (icopy = strdup(ichr)) == NULL);
731 |
732 | /* 3. chop trailing spaces */
733 | for( chr = icopy + strlen(icopy)-1 ;
734 | chr != icopy && isspace(*chr);
735 | chr--) {
736 | *chr = 0;
737 | }
738 |
739 | /* set thread accounting */
740 | TA_setactivity(icopy);
741 | TA_increment();
742 |
743 | connected = process_input(icopy, &condat);
744 |
745 | TA_setactivity("");
746 |
747 | free(icopy);
748 | }
749 |
750 | /* Log admin logging off */
751 | log_config(user, "logged off");
752 | }
753 |
754 | /* Close the socket */
755 | SK_close(sock);
756 |
757 | wr_free(condat.ip);
758 | } /* PC_interact() */
759 |