Work on ansi shell
This commit is contained in:
		| @ -1,9 +1,7 @@ | ||||
| #ifndef __ACTUBE_AC_H | ||||
| #define __ACTUBE_AC_H | ||||
|  | ||||
| #include "mavl.h" | ||||
| #include "cw/mavltypes.h" | ||||
|  | ||||
| #include "cw/cfg.h" | ||||
|  | ||||
| extern struct ac_status ac_global_status; | ||||
|  | ||||
| @ -19,7 +17,7 @@ enum { | ||||
| 	AC_PROTO_UNKNOWN | ||||
| }; | ||||
|  | ||||
| void start_shell(); | ||||
| int start_shell(cw_Cfg_t *global_cfg); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @ -52,8 +52,34 @@ int ac_run(cw_Cfg_t * cfg); | ||||
| #include "statemachine.h" | ||||
|  | ||||
| #include <getopt.h> | ||||
| #include <sys/socket.h> | ||||
| #include <sys/un.h> | ||||
|  | ||||
| /* | ||||
| void tshell_run(int fd) | ||||
| { | ||||
| 	int rc; | ||||
| 	printf("listening\n"); | ||||
| 	rc = listen(fd,5); | ||||
| 	printf("listen returned %d\n",rc); | ||||
| 	clientsock = accept (sockfd, (struct sockaddr*) &client, &client_size); | ||||
| 	 | ||||
|  | ||||
| } | ||||
|  | ||||
| void tshell() | ||||
| { | ||||
| 	printf("tshell start\n"); | ||||
| 	struct sockaddr_un addr; | ||||
|  | ||||
| 	int fd = socket(AF_UNIX, SOCK_STREAM, 0); | ||||
| 	memset(&addr, 0, sizeof(addr)); | ||||
| 	addr.sun_family = AF_UNIX; | ||||
| 	strncpy(addr.sun_path, "./tsocket", sizeof(addr.sun_path)-1); | ||||
| 	bind(fd, (struct sockaddr*)&addr, sizeof(addr)); | ||||
| 	while(1); | ||||
| } | ||||
| */ | ||||
|  | ||||
| struct bootcfg { | ||||
| 	const char * cfgfilename; | ||||
| @ -181,8 +207,6 @@ int main (int argc, char *argv[]) | ||||
| 	int rc = 0; | ||||
| 	struct bootcfg bootcfg; | ||||
|  | ||||
|  | ||||
|  | ||||
| 	/* parse arguments */ | ||||
| 	parse_args (argc, argv, &bootcfg); | ||||
|  | ||||
| @ -237,10 +261,6 @@ int main (int argc, char *argv[]) | ||||
| 	 | ||||
| 		 | ||||
|  | ||||
| 	 | ||||
| 		 | ||||
| 	start_shell(); | ||||
|  | ||||
| 	/* Init DTLS library */ | ||||
| 	dtls_init(); | ||||
| 		 | ||||
| @ -255,9 +275,15 @@ int main (int argc, char *argv[]) | ||||
| 	if (!dataman_list_init()) | ||||
| 		goto errX; | ||||
|  | ||||
|  | ||||
|  | ||||
| 	ac_conf_init(global_cfg); | ||||
|  | ||||
| 	cw_cfg_dump(global_cfg); | ||||
| 	if (!start_shell(global_cfg)) | ||||
| 		goto errX; | ||||
|  | ||||
|  | ||||
| //	cw_cfg_dump(global_cfg); | ||||
| 		 | ||||
| 	cw_log (LOG_INFO, "Starting AC-Tube, Name=%s, ID=%s", cw_cfg_get(global_cfg,"capwap/ac-name",NULL), conf_acid); | ||||
| 	rc = ac_run(global_cfg); | ||||
|  | ||||
| @ -298,7 +298,7 @@ int init_bcast_addrs(cw_Cfg_t *cfg) | ||||
| 			sr = mavl_add_str(t, s); | ||||
|  | ||||
|  | ||||
| 			printf("BCAST = %p --- %p: %s\n",str,s,str); | ||||
| //			printf("BCAST = %p --- %p: %s\n",str,s,str); | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| @ -549,7 +549,6 @@ int conf_parse_listen_addr(const char *addrstr, char *saddr, char *port, int *pr | ||||
|  | ||||
| void ac_conf_init(cw_Cfg_t *cfg) | ||||
| { | ||||
| 	printf("ac conf\n"); | ||||
| 	init_listen_addrs(cfg); | ||||
| 	init_bcast_addrs(cfg); | ||||
| 	init_ac_name(cfg); | ||||
|  | ||||
| @ -40,6 +40,11 @@ actube/ipv6: false | ||||
| actube/mod.1: capwap | ||||
| actube/mod.2: capwap80211 | ||||
|  | ||||
| #actube/shell/listen: unix:/tmp/actube | ||||
| actube/shell/listen: tcp:127.0.0.1:5000 | ||||
| actube/shell/enable: true | ||||
| actube/shell/term: ansi | ||||
|  | ||||
|  | ||||
| ac-descriptor/dtls-policy:  1 | ||||
| ac-descriptor/hardware/vendor: 4232704 | ||||
|  | ||||
							
								
								
									
										355
									
								
								src/ac/shell.c
									
									
									
									
									
								
							
							
						
						
									
										355
									
								
								src/ac/shell.c
									
									
									
									
									
								
							| @ -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,19 +588,26 @@ 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); | ||||
| @ -440,24 +616,61 @@ void shell_loop (FILE *file) | ||||
|  | ||||
|  | ||||
| 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); | ||||
| 	 | ||||
| 	if (rc) { | ||||
| 		cw_log (LOG_ERR, "Can't listen on address '%s', %s", addr, strerror (errno)); | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	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 sockfd;	 | ||||
| } | ||||
| 	 | ||||
| 	 | ||||
| 	 | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| void start_shell() | ||||
| 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 bind socket 'unix:%s', %s", name, strerror (errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	int clientsock = accept (fd, (struct sockaddr*) &client, &client_size); | ||||
|  | ||||
| 	return fd; | ||||
| } | ||||
|  | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| @ -25,4 +25,8 @@ | ||||
| #define ANSI_ITALIC	"\x1b[3m" | ||||
| #define ANSI_BOLD	"\x1b[1m" | ||||
|  | ||||
|  | ||||
| #define ANSI_HOME	"[H" | ||||
|  | ||||
|  | ||||
| #endif /* __ANSI_COLORS_H */ | ||||
|  | ||||
| @ -31,6 +31,7 @@ | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <sys/un.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <netinet/in.h> | ||||
|  | ||||
| @ -88,7 +89,7 @@ char *sock_addrtostr(const struct sockaddr *sa, char *s, size_t maxlen, int addp | ||||
| 		} | ||||
| 			break; | ||||
|  | ||||
| #endif				/* AF_LINLK */ | ||||
| #endif	/* AF_LINLK */ | ||||
|  | ||||
| #ifdef AF_PACKET | ||||
| 		case AF_PACKET: | ||||
| @ -103,11 +104,17 @@ char *sock_addrtostr(const struct sockaddr *sa, char *s, size_t maxlen, int addp | ||||
| 			sprintf(sp, "%02X", sl->sll_addr[i]); | ||||
| 		} | ||||
| 			break; | ||||
| #endif				/* AF_PACKET */ | ||||
| #endif	/* AF_PACKET */ | ||||
| 		case AF_UNIX: | ||||
| 		{ | ||||
| 			struct sockaddr_un *addr = (struct sockaddr_un *) sa; | ||||
| 			snprintf(s, maxlen, "%s", addr->sun_path); | ||||
| 		} | ||||
| 			break; | ||||
|  | ||||
|  | ||||
| 		default: | ||||
| 			strncpy(s, "Unknown AF", maxlen); | ||||
| 			snprintf(s,maxlen, "Unknown AF: %d", sa->sa_family); | ||||
| 			return NULL; | ||||
| 	} | ||||
| 	return s; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user