|
|
|
@ -5,6 +5,10 @@ |
|
|
|
|
|
|
|
|
|
#include <sys/types.h> |
|
|
|
|
#include <sys/socket.h> |
|
|
|
|
#include <sys/un.h> |
|
|
|
|
#include <arpa/telnet.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "cw/sock.h" |
|
|
|
|
#include "cw/log.h" |
|
|
|
@ -16,13 +20,24 @@ |
|
|
|
|
|
|
|
|
|
#include "wtplist.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "ac.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct shelldata{ |
|
|
|
|
FILE *out; |
|
|
|
|
char prompt[1024]; |
|
|
|
|
mavl_t update_cfg; |
|
|
|
|
char *history[2000]; |
|
|
|
|
char line[4096]; |
|
|
|
|
int pos; |
|
|
|
|
char esc[8]; |
|
|
|
|
int escpos; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct sockdata{ |
|
|
|
|
const char *name; |
|
|
|
|
int fd; |
|
|
|
|
cw_Cfg_t * global_cfg; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
void select_cmd(struct shelldata *sd, const char *cmd); |
|
|
|
@ -408,6 +423,160 @@ void execute_cmd (struct shelldata * sd, const char *str) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct esc_strings { |
|
|
|
|
char *str; |
|
|
|
|
char * result; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct esc_strings estr[] = { |
|
|
|
|
{"\x1b[H", "home"}, |
|
|
|
|
{"\x1b[F", "end"}, |
|
|
|
|
{"\x1b[A", "up"}, |
|
|
|
|
{"\x1b[B", "donw"}, |
|
|
|
|
{"\x1b[D", "left"}, |
|
|
|
|
{"\x1b[C", "right"}, |
|
|
|
|
|
|
|
|
|
{NULL,NULL} |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int cmpansi(char * str,char * ansistr) |
|
|
|
|
{ |
|
|
|
|
int sl,al; |
|
|
|
|
sl = strlen(str); |
|
|
|
|
al = strlen(ansistr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(sl>al){ |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
if (sl<al){ |
|
|
|
|
if (strncmp(str,ansistr,sl)==0) |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (strcmp(str,ansistr)==0) |
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void get_line_char_mode(FILE * file, struct shelldata *sd) |
|
|
|
|
{ |
|
|
|
|
int c; |
|
|
|
|
struct esc_strings * es; |
|
|
|
|
|
|
|
|
|
es = NULL; |
|
|
|
|
sd->line[0]=0; |
|
|
|
|
sd->pos=0; |
|
|
|
|
sd->esc[0]=0; |
|
|
|
|
sd->escpos=0; |
|
|
|
|
|
|
|
|
|
// fprintf (file, "\xff\xfc\22");
|
|
|
|
|
|
|
|
|
|
/* Put telnet into char mode */ |
|
|
|
|
fprintf (file,"%c%c%c",IAC,WILL,TELOPT_ECHO ); |
|
|
|
|
fprintf (file,"%c%c%c",IAC,WILL,TELOPT_SGA ); |
|
|
|
|
// fprintf (file,"%c%c%c",IAC,DONT,TELOPT_LINEMODE );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fprintf (file, "\n\ractube[%s]:>", sd->prompt); |
|
|
|
|
fflush (file); |
|
|
|
|
|
|
|
|
|
while ( (c=fgetc(file))!= EOF){ |
|
|
|
|
printf ("%02x\n",c); |
|
|
|
|
if (sd->escpos){ |
|
|
|
|
int i; |
|
|
|
|
int a=0; |
|
|
|
|
|
|
|
|
|
sd->esc[sd->escpos++]=c; |
|
|
|
|
sd->esc[sd->escpos]=0; |
|
|
|
|
|
|
|
|
|
for (i=0; estr[i].str != NULL; i++){ |
|
|
|
|
int rc; |
|
|
|
|
rc = cmpansi(sd->esc,estr[i].str); |
|
|
|
|
if (rc==1){ |
|
|
|
|
sd->esc[0]=0; |
|
|
|
|
sd->escpos=0; |
|
|
|
|
es = &estr[i]; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
a |= rc; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (a==0){ |
|
|
|
|
sd->esc[0]=0; |
|
|
|
|
sd->escpos=0; |
|
|
|
|
}else{ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (c==0x1b){ |
|
|
|
|
sd->esc[sd->escpos++]=c; |
|
|
|
|
sd->esc[sd->escpos]=0; |
|
|
|
|
printf("ESC start\n"); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!es){ |
|
|
|
|
if (c=='\r'){ |
|
|
|
|
printf("CMD: %s\n",sd->line); |
|
|
|
|
fprintf (file, "\n\ractube[%s]:>", sd->prompt); |
|
|
|
|
sd->pos=0; |
|
|
|
|
sd->line[0]=0; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (c=='\x7f'){ |
|
|
|
|
if (sd->pos==0) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
printf("Backspace\n"); |
|
|
|
|
fprintf(file,"%c %c",8,8); |
|
|
|
|
sd->line[--sd->pos]=0; |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
if (c>240 || c<30){ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sd->line[sd->pos++]=c; |
|
|
|
|
sd->line[sd->pos]=0; |
|
|
|
|
printf("putout: %c %02X\n",c,c); |
|
|
|
|
fprintf(file,"%c",c); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf ("ES: %s\n",es->result); |
|
|
|
|
|
|
|
|
|
if (strcmp(es->result,"left")==0){ |
|
|
|
|
if (sd->pos>0){ |
|
|
|
|
sd->pos--; |
|
|
|
|
fprintf(file,es->str); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (strcmp(es->result,"right")==0){ |
|
|
|
|
if (sd->line[sd->pos]!=0){ |
|
|
|
|
sd->pos++; |
|
|
|
|
fprintf(file,es->str); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// fprintf(file,es->str);
|
|
|
|
|
|
|
|
|
|
es = NULL; |
|
|
|
|
// fflush(file);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void shell_loop (FILE *file) |
|
|
|
|
{ |
|
|
|
@ -419,45 +588,89 @@ void shell_loop (FILE *file) |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
char str[2048]; |
|
|
|
|
stop(); |
|
|
|
|
// sd.update_cfg = cw_ktv_create();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sd.out = file; |
|
|
|
|
sprintf(sd.prompt,"%s","*"); |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
fprintf (file, "actube[%s]:>", sd.prompt); |
|
|
|
|
fflush (file); |
|
|
|
|
int c; |
|
|
|
|
get_line_char_mode(file,&sd); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
str[0]=0; |
|
|
|
|
// c=fgetc(file);
|
|
|
|
|
|
|
|
|
|
printf("%c\n",c); |
|
|
|
|
|
|
|
|
|
fgets (str, sizeof (str), file); |
|
|
|
|
|
|
|
|
|
printf("My String: %s\n",str); |
|
|
|
|
|
|
|
|
|
execute_cmd (&sd, str); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} while (c != EOF); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void * run_shell (void * arg) |
|
|
|
|
{ |
|
|
|
|
char sockstr[SOCK_ADDR_BUFSIZE]; |
|
|
|
|
struct sockdata * sockdata; |
|
|
|
|
int clientsock; |
|
|
|
|
struct sockaddr_storage client; |
|
|
|
|
socklen_t client_size; |
|
|
|
|
|
|
|
|
|
sockdata = (struct sockdata *)arg; |
|
|
|
|
|
|
|
|
|
memset(&client,0,sizeof(client)); |
|
|
|
|
client_size=sizeof(client); |
|
|
|
|
|
|
|
|
|
cw_dbg(DBG_INFO,"Starting shell, listening on: %s (sock fd: %d)",sockdata->name, sockdata->fd); |
|
|
|
|
|
|
|
|
|
while(1){ |
|
|
|
|
clientsock = accept (sockdata->fd, (struct sockaddr*) &client, &client_size); |
|
|
|
|
if (clientsock == -1){ |
|
|
|
|
cw_log (LOG_ERR, "Accept error '%s', %s", "addr", strerror (errno)); |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (clientsock > 0) { |
|
|
|
|
sock_addr2str_p (&client, sockstr); |
|
|
|
|
cw_dbg (DBG_INFO, "Acceptiong session from %s", sockstr); |
|
|
|
|
cw_dbg (DBG_INFO, "Start shell"); |
|
|
|
|
shell_loop (fdopen (clientsock, "a+")); |
|
|
|
|
cw_dbg (DBG_INFO, "Stop shell"); |
|
|
|
|
close (clientsock); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//cw_dbg (DBG_INFO,"Accepting shell session %i, %s", rc, strerror (errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int create_tcp_fd(const char *name) |
|
|
|
|
{ |
|
|
|
|
struct sockaddr_storage server, client; |
|
|
|
|
socklen_t client_size; |
|
|
|
|
char sockstr[SOCK_ADDR_BUFSIZE]; |
|
|
|
|
|
|
|
|
|
int rc; |
|
|
|
|
const char * addr = "127.0.0.1:5000"; |
|
|
|
|
const char * addr = name; |
|
|
|
|
int sockfd, clientsock; |
|
|
|
|
int yes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cw_dbg(DBG_INFO,"Staring shelli listening at: %s",addr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rc = sock_strtoaddr (addr, (struct sockaddr*) &server); |
|
|
|
|
|
|
|
|
|
if (! rc) { |
|
|
|
|
cw_log (LOG_ERR, "Can't parse address '%s', %s", addr, strerror (errno)); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sockfd = socket ( ( (struct sockaddr*) &server)->sa_family, SOCK_STREAM, 0); |
|
|
|
@ -472,43 +685,99 @@ void * run_shell (void * arg) |
|
|
|
|
|
|
|
|
|
if (rc) { |
|
|
|
|
cw_log (LOG_ERR, "Can't bind socket address '%s', %s", addr, strerror (errno)); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rc = listen (sockfd, 5); |
|
|
|
|
|
|
|
|
|
return sockfd;
|
|
|
|
|
} |
|
|
|
|
static int create_unix_fd(const char *name) |
|
|
|
|
{ |
|
|
|
|
struct sockaddr_storage client; |
|
|
|
|
socklen_t client_size; |
|
|
|
|
struct sockaddr_un addr; |
|
|
|
|
int rc,fd; |
|
|
|
|
|
|
|
|
|
unlink(name); |
|
|
|
|
fd = socket(PF_UNIX, SOCK_STREAM, 0); |
|
|
|
|
|
|
|
|
|
memset(&addr, 0, sizeof(addr)); |
|
|
|
|
addr.sun_family = AF_UNIX; |
|
|
|
|
strncpy(addr.sun_path, name, sizeof(addr.sun_path)-1); |
|
|
|
|
rc = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); |
|
|
|
|
if (rc) { |
|
|
|
|
cw_log (LOG_ERR, "Can't listen on address '%s', %s", addr, strerror (errno)); |
|
|
|
|
cw_log (LOG_ERR, "Can't bind socket 'unix:%s', %s", name, strerror (errno)); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client_size = sizeof (client); |
|
|
|
|
while(1){ |
|
|
|
|
|
|
|
|
|
clientsock = accept (sockfd, (struct sockaddr*) &client, &client_size); |
|
|
|
|
|
|
|
|
|
if (clientsock > 0) { |
|
|
|
|
sock_addr2str_p (&client, sockstr); |
|
|
|
|
cw_dbg (DBG_INFO, "Acceptiong session from %s", sockstr); |
|
|
|
|
cw_dbg (DBG_INFO, "Start shell"); |
|
|
|
|
shell_loop (fdopen (clientsock, "a+")); |
|
|
|
|
cw_dbg (DBG_INFO, "Stop shell"); |
|
|
|
|
close (clientsock); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cw_dbg (DBG_INFO,"Accepting shell session %i, %s", rc, strerror (errno)); |
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
int clientsock = accept (fd, (struct sockaddr*) &client, &client_size); |
|
|
|
|
|
|
|
|
|
return fd; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void start_shell() |
|
|
|
|
int start_shell(cw_Cfg_t *global_cfg) |
|
|
|
|
{ |
|
|
|
|
struct sockdata * sockdata; |
|
|
|
|
const char *sockname; |
|
|
|
|
int rc, type; |
|
|
|
|
int fd; |
|
|
|
|
|
|
|
|
|
rc = cw_cfg_get_bool(global_cfg,"actube/shell/enable",1); |
|
|
|
|
if (!rc) |
|
|
|
|
return 1; |
|
|
|
|
|
|
|
|
|
sockdata = malloc(sizeof(struct sockdata)); |
|
|
|
|
if (sockdata==NULL) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
memset(sockdata,0,sizeof(struct sockdata)); |
|
|
|
|
|
|
|
|
|
sockdata->global_cfg = global_cfg; |
|
|
|
|
sockdata->fd=-1; |
|
|
|
|
|
|
|
|
|
sockname = cw_cfg_get(global_cfg,"actube/shell/listen",NULL); |
|
|
|
|
|
|
|
|
|
if (sockname==NULL) { |
|
|
|
|
cw_log (LOG_ERR, "Can't get shell listen address from global_cfg 'actube/shell/listen"); |
|
|
|
|
goto errX; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (strncmp("unix:",sockname,strlen("unix:"))==0){ |
|
|
|
|
fd = create_unix_fd(strchr(sockname,':')+1); |
|
|
|
|
if (fd==-1) |
|
|
|
|
goto errX; |
|
|
|
|
sockdata->name=cw_strdup(sockname); |
|
|
|
|
sockdata->fd=fd; |
|
|
|
|
}else if (strncmp("tcp:",sockname,strlen("tcp:"))==0){ |
|
|
|
|
fd = create_tcp_fd(strchr(sockname,':')+1); |
|
|
|
|
if (fd==-1) |
|
|
|
|
goto errX; |
|
|
|
|
sockdata->name=cw_strdup(sockname); |
|
|
|
|
sockdata->fd=fd; |
|
|
|
|
}else { |
|
|
|
|
fd = create_tcp_fd(sockname); |
|
|
|
|
if (fd==-1) |
|
|
|
|
goto errX; |
|
|
|
|
sockdata->name=cw_strdup(sockname); |
|
|
|
|
sockdata->fd=fd; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rc = listen (sockdata->fd, 5); |
|
|
|
|
if (rc) { |
|
|
|
|
cw_log (LOG_ERR, "Can't listen on address '%s', %s", "addr", strerror (errno)); |
|
|
|
|
goto errX; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pthread_t thread; |
|
|
|
|
pthread_create (&thread, NULL, run_shell, |
|
|
|
|
NULL); |
|
|
|
|
sockdata); |
|
|
|
|
return 1; |
|
|
|
|
errX: |
|
|
|
|
if (sockdata->fd!=-1) |
|
|
|
|
close(sockdata->fd); |
|
|
|
|
if (sockdata->name) |
|
|
|
|
free(sockdata->name); |
|
|
|
|
|
|
|
|
|
free(sockdata); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|