src/dietline.c
author pancake
Tue Dec 08 20:22:45 2009 +0100 (2009-12-08)
changeset 1242 b55faadb4a4a
parent 1201 f605a3a8796c
child 1245 563178270848
permissions -rw-r--r--
* Huge dewarnification.. some segfaults fixed
     1 /*
     2  * Copyright (C) 2007, 2008, 2009
     3  *       pancake <youterm.com>
     4  *
     5  * dietline is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * dietline is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License
    16  * along with dietline; if not, write to the Free Software
    17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18  *
    19  */
    20 
    21 #include "dietline.h"
    22 
    23 /* dietline is a lighweight and portable library similar to GNU readline */
    24 
    25 #if RADARE_CORE
    26 #include "main.h"
    27 #else
    28 static void cons_set_raw(int b);
    29 static int cons_get_real_columns();
    30 #define __UNIX__ 1
    31 #endif
    32 
    33 #include <string.h>
    34 #include <stdlib.h>
    35 
    36 #if __WINDOWS__
    37 #include <windows.h>
    38 #else
    39 #include <sys/ioctl.h>
    40 #include <termios.h>
    41 #include <signal.h>
    42 #endif
    43 
    44 /* line input */
    45 int dl_echo = 1;
    46 const char *dl_prompt = "> ";
    47 const char *dl_clipboard = NULL;
    48 static char *dl_nullstr = "";
    49 static char dl_buffer[DL_BUFSIZE];
    50 static int dl_buffer_len = 0;
    51 static int dl_buffer_idx = 0;
    52 
    53 /* autocompletion callback */
    54 char **(*dl_callback)(const char *text, int start, int end) = NULL;
    55 
    56 /* history */
    57 char **dl_history = NULL;
    58 int dl_histsize = DL_HISTSIZE;
    59 int dl_histidx = 0;
    60 int dl_autosave = 0; // TODO
    61 int dl_disable = 0; // TODO use fgets..no autocompletion
    62 
    63 // TODO : FULL READLINE COMPATIBILITY
    64 // rl_attempted_completion_function = rad_autocompletion;
    65 // char **rad_autocompletion(const char *text, int start, int end)
    66 // return  matches = rl_completion_matches (text, rad_offset_matches);
    67 
    68 int dl_readchar()
    69 {
    70 	char buf[2];
    71 #if __WINDOWS__
    72 	LPDWORD out;
    73 	BOOL ret;
    74 	LPDWORD mode;
    75 	HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
    76 
    77 	GetConsoleMode(h, &mode);
    78 	SetConsoleMode(h, 0); // RAW
    79 	ret = ReadConsole(h, buf,1, &out, NULL);
    80 	if (!ret) {
    81 		// wine hack-around
    82 		if (read(0,buf,1) == 1)
    83 			return buf[0];
    84 		return -1;
    85 	}
    86 	SetConsoleMode(h, mode);
    87 #else
    88 	int ret = read(0,buf,1);
    89 	if (ret <1)
    90 		return -1;
    91 #endif
    92 	return buf[0];
    93 }
    94 
    95 /* scripting */
    96 
    97 #define BLOCK 4096
    98 static char *labels = NULL;
    99 static unsigned int size = 0;
   100 static unsigned int lsize = 0;
   101 
   102 static int label_get(const char *name)
   103 {
   104 	int i, n;
   105 	for(i=0;i<size;i++) {
   106 		if (!strcmp(name, labels+i+4)) {
   107 			memcpy(&n, labels+i, 4);
   108 			return n;
   109 		}
   110 		i+=strlen(labels+i+4)+4;
   111 	}
   112 	return -1;
   113 }
   114 
   115 static void label_add (const char *str) {
   116 	unsigned int size = dl_histidx;
   117 	unsigned int len = strlen(str)-1;
   118 
   119 	//eprintf("New label(%s)\n",str);
   120 	memset(labels+lsize+4, '\0', BLOCK-((lsize+len+4)%BLOCK));
   121 	memcpy(labels+lsize, &size, 4);
   122 	memcpy(labels+lsize+4, str, len);
   123 	lsize+=len+4+1;
   124 }
   125 
   126 void dl_label_show()
   127 {
   128 	unsigned int i, p, n = 0;
   129 	for(i=0;i<lsize;i++,n++) {
   130 		memcpy(&p, labels+i, 4);
   131 		printf(" %03d %03d  %s\n", i, p, labels+i+4);
   132 		i+=strlen(labels+i+4)+4;
   133 	}
   134 }
   135 
   136 static void label_reset()
   137 {
   138 	lsize = 0;
   139 	free(labels);
   140 	labels = NULL;
   141 }
   142 
   143 static int is_label(const char *str)
   144 {
   145 	/* crappy hack */
   146 	return 0;
   147 
   148 	if (str[0]=='\0')
   149 		return 0;
   150 	if (str[strlen(str)-1]==':') {
   151 		if (str[0]==':') {
   152 			dl_label_show();
   153 			return 2;
   154 		}
   155 		return 1;
   156 	}
   157 	return 0;
   158 }
   159 
   160 /* history stuff */
   161 
   162 int dl_hist_label(const char *label, void (*cb)(const char*))
   163 {
   164 	int i;
   165 #if 1
   166 	/* labelling stuff */
   167 	if (label[0]=='.') {
   168 		if (!is_label(label+1))
   169 			return 0;
   170 	} else {
   171 		switch(is_label(label)) {
   172 		case 0:
   173 		case 2:
   174 			return 0;
   175 		}
   176 	}
   177 
   178 	i = label_get(label);
   179 	if (i == -1) {
   180 		label_add(label);
   181 		return 1;
   182 	}
   183 #endif
   184 	if (dl_history != NULL)
   185 	for(i=0; i<dl_histsize; i++) {
   186 		if (dl_history[i] == NULL)
   187 			break;
   188 		fprintf(stderr, "%s\n", dl_history[i]);
   189 		if (cb != NULL)
   190 			cb(dl_history[i]);
   191 		else	fprintf(stderr, "%s\n", dl_history[i]);
   192 	}
   193 
   194 	return 1;
   195 }
   196 
   197 int dl_hist_add(const char *line)
   198 {
   199 #if HAVE_LIB_READLINE
   200 	add_history(line);
   201 #endif
   202 	if (dl_histidx>=dl_histsize)
   203 		dl_histidx = 0; // workaround
   204 	if (*line) { // && dl_histidx < dl_histsize) {
   205 		dl_history[dl_histidx++] = strdup(line);
   206 		return 1;
   207 	}
   208 	return 0;
   209 //#endif
   210 }
   211 
   212 int dl_hist_up()
   213 {
   214 	if (dl_histidx>0) {
   215 		strncpy(dl_buffer, dl_history[--dl_histidx], DL_BUFSIZE-1);
   216 		dl_buffer_idx=
   217 		dl_buffer_len = strlen(dl_buffer);
   218 		return 1;
   219 	}
   220 	return 0;
   221 }
   222 
   223 int dl_hist_down()
   224 {
   225 	dl_buffer_idx=0;
   226 	if (dl_histidx<dl_histsize) {
   227 		if (dl_history[dl_histidx] == NULL) {
   228 			dl_buffer[0]='\0';
   229 			dl_buffer_idx = dl_buffer_len = 0;
   230 			return 0;
   231 		}
   232 		strncpy(dl_buffer, dl_history[dl_histidx++], DL_BUFSIZE-1);
   233 		dl_buffer_idx=
   234 		dl_buffer_len = strlen(dl_buffer);
   235 		return 1;
   236 	}
   237 	return 0;
   238 }
   239 
   240 int dl_hist_list()
   241 {
   242 	int i = 0;
   243 
   244 	if (dl_history != NULL)
   245 	for(i=0;i<dl_histsize; i++) {
   246 		if (dl_history[i] == NULL)
   247 			break;
   248 		printf("%.3d  %s\n", i, dl_history[i]);
   249 	}
   250 
   251 	return i;
   252 }
   253 
   254 int dl_hist_free()
   255 {
   256 	int i;
   257 	if (dl_history != NULL)
   258 	for(i=0;i<dl_histsize; i++) {
   259 		free(dl_history[i]);
   260 		dl_history[i] = NULL;
   261 	}
   262 	return dl_histidx=0, dl_histsize;
   263 }
   264 
   265 void dl_free()
   266 {
   267 	printf("Bye!\n");
   268 	dl_hist_free();
   269 	label_reset();
   270 	free(dl_history);
   271 }
   272 
   273 /* load history from file. if file == NULL load from ~/.<prg>.history or so */
   274 int dl_hist_load(const char *file)
   275 {
   276 #if HAVE_LIB_READLINE
   277 	rad_readline_init();
   278 	return 0;
   279 #else
   280 	char buf[1024];
   281 	FILE *fd;
   282 
   283 	snprintf(buf, 1023, "%s/%s", get_home_directory(), file);
   284 	fd = fopen(buf, "r");
   285 	if (fd == NULL)
   286 		return 0;
   287 
   288 	fgets(buf, 1023, fd);
   289 	while (!feof(fd)) {
   290 		buf[strlen(buf)-1]='\0';
   291 		dl_hist_add(buf);
   292 		fgets(buf, 1023, fd);
   293 	}
   294 	fclose(fd);
   295 
   296 	return 1;
   297 #endif
   298 }
   299 
   300 int dl_hist_save(const char *file)
   301 {
   302 #if HAVE_LIB_READLINE
   303 	rad_readline_finish();
   304 #else
   305 	char buf[1024];
   306 	FILE *fd;
   307 	int i;
   308 
   309 	snprintf(buf, 1023, "%s/%s", get_home_directory(), file);
   310 	fd = fopen(buf, "w");
   311 	if (fd == NULL)
   312 		return 0;
   313 	for(i=0;i<dl_histidx;i++) {
   314 		fputs(dl_history[i], fd);
   315 		fputs("\n", fd);
   316 	}
   317 	fclose(fd);
   318 	
   319 	return 1;
   320 #endif
   321 }
   322 
   323 int dl_hist_chop(const char *file, int limit)
   324 {
   325 	/* TODO */
   326 	return 0;
   327 }
   328 
   329 /* initialize history stuff */
   330 int dl_init()
   331 {
   332 #if HAVE_LIB_READLINE
   333 	rad_readline_init();
   334 #endif
   335 	if (labels==NULL)
   336 		labels = malloc(BLOCK);
   337 	dl_history = (char **)malloc(dl_histsize*sizeof(char *));
   338 	if (dl_history==NULL)
   339 		return 0;
   340 	memset(dl_history, '\0', dl_histsize*sizeof(char *));
   341 	dl_histidx = 0;
   342 	dl_histsize = DL_HISTSIZE;
   343 	dl_histidx = 0;
   344 	dl_autosave = 0;
   345 	dl_disable = 0;
   346 	return 1;
   347 }
   348 
   349 /* test */
   350 int dl_printchar()
   351 {
   352 	unsigned char buf[10];
   353 
   354 	cons_set_raw(1);
   355 	buf[0]=dl_readchar();
   356 
   357 	switch(buf[0]) {
   358 		case 226:
   359 		case 197:
   360 		case 195:
   361 		case 194:
   362 			buf[0] = dl_readchar();
   363 			printf("unicode-%02x-%02x\n", buf[0],buf[1]);
   364 			break;
   365 		case 8: // wtf is 127?
   366 		case 127: printf("backspace\n"); break;
   367 		case 32: printf("space\n"); break;
   368 		case 27:
   369 			read(0, buf, 5);
   370 			printf("esc-%02x-%02x-%02x-%02x\n",
   371 					buf[0],buf[1],buf[2],buf[3]);
   372 			break;
   373 		case 12: printf("^L\n"); break;
   374 		case 13: printf("intro\n"); break;
   375 		case 18: printf("^R\n"); break;
   376 		case 9: printf("tab\n"); break;
   377 		case 3: printf("control-c\n"); break;
   378 		case 0: printf("control-space\n"); break;
   379 		default:
   380 			printf("(code:%d)\n", buf[0]);
   381 			break;
   382 	}
   383 
   384 	cons_set_raw(0);
   385 
   386 	return buf[0];
   387 }
   388 
   389 /* main readline function */
   390 char *dl_readline(int argc, const char **argv)
   391 {
   392 	int buf[10];
   393 	int i, len = 0;
   394 	int opt = 0;
   395 	int columns = cons_get_real_columns()-2;
   396 
   397 	dl_buffer_idx = dl_buffer_len = 0;
   398 	dl_buffer[0]='\0';
   399 
   400 #if RADARE_CORE
   401 	dl_echo = config.verbose;
   402 #endif
   403 
   404 	if (dl_disable) {
   405 		dl_buffer[0]='\0';
   406 		fgets(dl_buffer, DL_BUFSIZE-1, stdin);
   407 		dl_buffer[strlen(dl_buffer)] = '\0';
   408 		return (*dl_buffer)? dl_buffer : NULL;
   409 	}
   410 
   411 	memset(&buf,0,sizeof buf);
   412 	cons_set_raw(1);
   413 
   414 	if (dl_echo) {
   415 		printf("%s", dl_prompt);
   416 		fflush(stdout);
   417 	}
   418 
   419 #if __UNIX__
   420 	if (feof(stdin))
   421 		return NULL;
   422 #endif
   423 
   424 	while(1) {
   425 #if 0
   426 		if (dl_echo) {
   427 			printf("  (");
   428 			for(i=1;i<argc;i++) {
   429 				if (dl_buffer_len==0||!strncmp(argv[i], dl_buffer, dl_buffer_len)) {
   430 					len+=strlen(argv[i])+1;
   431 					if (len+dl_buffer_len+4 >= columns) break;
   432 					printf("%s ", argv[i]);
   433 				}
   434 			}
   435 			printf(")");
   436 			fflush(stdout);
   437 		}
   438 #endif
   439 
   440 		dl_buffer[dl_buffer_len]='\0';
   441 		buf[0] = dl_readchar();
   442 		
   443 //		printf("\x1b[K\r");
   444 		columns = cons_get_real_columns()-2;
   445 		if (columns <1)
   446 			columns = 40;
   447 		if (dl_echo)
   448 		printf("\r%*c\r", columns, ' ');
   449 
   450 		switch(buf[0]) {
   451 			case -1:
   452 				return NULL;
   453 			case 0: // control-space
   454 				/* ignore atm */
   455 				break;
   456 			case 1: // ^A
   457 				dl_buffer_idx = 0;
   458 				break;
   459 			case 5: // ^E
   460 				dl_buffer_idx = dl_buffer_len;
   461 				break;
   462 			case 3: // ^C 
   463 				if (dl_echo)
   464 					printf("\n^C\n");
   465 				dl_buffer[dl_buffer_idx = dl_buffer_len = 0] = '\0';
   466 				goto _end;
   467 			case 4: // ^D
   468 				if (dl_echo)
   469 					printf("^D\n");
   470 				if (!dl_buffer[0]) { /* eof */
   471 					cons_set_raw(0);
   472 					return NULL;
   473 				}
   474 				break;
   475 			case 10: // ^J -- ignore
   476 				return dl_buffer;
   477 			case 11: // ^K -- ignore
   478 				break;
   479 			case 19: // ^S -- backspace
   480 				dl_buffer_idx = dl_buffer_idx?dl_buffer_idx-1:0;
   481 				break;
   482 			case 12: // ^L -- right
   483 				dl_buffer_idx = dl_buffer_idx<dl_buffer_len?dl_buffer_idx+1:dl_buffer_len;
   484 				if (dl_echo)
   485 					printf("\x1b[2J\x1b[0;0H");
   486 				fflush(stdout);
   487 				break;
   488 			case 21: // ^U - cut
   489 				dl_clipboard = strdup(dl_buffer);
   490 				dl_buffer[0]='\0';
   491 				dl_buffer_len = 0;
   492 				dl_buffer_idx = 0;
   493 				break;
   494 			case 23: // ^W
   495 				if (dl_buffer_idx>0) {
   496 					for(i=dl_buffer_idx-1;i&&dl_buffer[i]==' ';i--);
   497 					for(;i&&dl_buffer[i]!=' ';i--);
   498 					for(;i>0&&dl_buffer[i]==' ';i--);
   499 					if (i>1) {
   500 						if (dl_buffer[i+1]==' ')
   501 						i+=2;
   502 					} else if (i<0) i=0;
   503 					strcpy(dl_buffer+i, dl_buffer+dl_buffer_idx);
   504 					dl_buffer_len = strlen(dl_buffer);
   505 					dl_buffer_idx = i;
   506 				}
   507 				break;
   508 			case 25: // ^Y - paste
   509 				if (dl_clipboard != NULL) {
   510 					dl_buffer_len += strlen(dl_clipboard);
   511 					// TODO: support endless strings
   512 					if (dl_buffer_len < DL_BUFSIZE) {
   513 						dl_buffer_idx = dl_buffer_len;
   514 						strcat(dl_buffer, dl_clipboard);
   515 					} else dl_buffer_len -= strlen(dl_clipboard);
   516 				}
   517 				break;
   518 			case 16:
   519 				dl_hist_up();
   520 				break;
   521 			case 14:
   522 				dl_hist_down();
   523 				break;
   524 			case 27: //esc-5b-41-00-00
   525 				buf[0] = dl_readchar();
   526 				buf[1] = dl_readchar();
   527 				if (buf[0]==0x5b) {
   528 					switch(buf[1]) {
   529 					case 0x33: // supr
   530 						if (dl_buffer_idx<dl_buffer_len)
   531 							strcpy(dl_buffer, dl_buffer+1);
   532 						break;
   533 					/* arrows */
   534 					case 0x41:
   535 						dl_hist_up();
   536 						break;
   537 					case 0x42:
   538 						dl_hist_down();
   539 						break;
   540 					case 0x43:
   541 						dl_buffer_idx = dl_buffer_idx<dl_buffer_len?dl_buffer_idx+1:dl_buffer_len;
   542 						break;
   543 					case 0x44:
   544 						dl_buffer_idx = dl_buffer_idx?dl_buffer_idx-1:0;
   545 						break;
   546 					}
   547 				}
   548 
   549 				break;
   550 			case 8:
   551 			case 127:
   552 				if (dl_buffer_idx < dl_buffer_len) {
   553 					if (dl_buffer_idx>0) {
   554 						dl_buffer_idx--;
   555 						memcpy(dl_buffer+dl_buffer_idx, dl_buffer+dl_buffer_idx+1,strlen(dl_buffer+dl_buffer_idx));
   556 					}
   557 				} else {
   558 					dl_buffer_idx = --dl_buffer_len;
   559 					if (dl_buffer_len<0) dl_buffer_len=0;
   560 					dl_buffer[dl_buffer_len]='\0';
   561 				}
   562 				if (dl_buffer_idx<0)
   563 					dl_buffer_idx = 0;
   564 				break;
   565 			case 9:// tab
   566 				/* autocomplete */
   567 				// XXX does not autocompletes correctly
   568 				// XXX needs to check if valid results have the same prefix (from 1 to N)
   569 				if (dl_callback != NULL) {
   570 					//const char *from = strrchr(dl_buffer, ' ');
   571 					//char **res = dl_callback(dl_buffer, (from==NULL)?dl_buffer_idx:from-dl_buffer, dl_buffer_len);
   572 					/* TODO: manage res */
   573 				} else {
   574 					if (dl_buffer_idx>0)
   575 					for(i=1,opt=0;i<argc;i++)
   576 						if (!strncmp(argv[i], dl_buffer, dl_buffer_idx))
   577 							opt++;
   578 
   579 					if (dl_buffer_len>0&&opt==1)
   580 						for(i=1;i<argc;i++) {
   581 							if (!strncmp(dl_buffer, argv[i], dl_buffer_len)) {
   582 								strcpy(dl_buffer, argv[i]);
   583 								dl_buffer_idx = dl_buffer_len = strlen(dl_buffer);
   584 								// TODO: if only 1 keyword hits:
   585 								//		if (argv[i][dl_buffer_len]=='\0') {
   586 								//			strcat(dl_buffer, " ");
   587 								//			dl_buffer_len++;
   588 								//		}
   589 								break;
   590 							}
   591 						}
   592 
   593 					/* show options */
   594 					if (dl_buffer_idx==0 || opt>1) {
   595 						if (dl_echo)
   596 							printf("%s%s\n",dl_prompt,dl_buffer);
   597 						for(i=1;i<argc;i++) {
   598 							if (dl_buffer_len==0||!strncmp(argv[i], dl_buffer, dl_buffer_len)) {
   599 								len+=strlen(argv[i]);
   600 					//			if (len+dl_buffer_len+4 >= columns) break;
   601 								if (dl_echo)
   602 									printf("%s ", argv[i]);
   603 							}
   604 						}
   605 						if (dl_echo)
   606 							printf("\n");
   607 					}
   608 					fflush(stdout);
   609 				}
   610 				break;
   611 			case 18:
   612 				// TODO: SUPPORT FOR ^R (search command in history)
   613 				break;
   614 			case 13: 
   615 				goto _end;
   616 #if 0
   617 				// force command fit
   618 				for(i=1;i<argc;i++) {
   619 					if (dl_buffer_len==0 || !strncmp(argv[i], dl_buffer, dl_buffer_len)) {
   620 						printf("%*c", columns, ' ');
   621 						printf("\r");
   622 						printf("\n\n(%s)\n\n", dl_buffer);
   623 						cons_set_raw(0);
   624 						return dl_buffer;
   625 					}
   626 				}
   627 #endif
   628 			default:
   629 				/* XXX use ^A & ^E */
   630 				if (dl_buffer_idx<dl_buffer_len) {
   631 					for(i = ++dl_buffer_len;i>dl_buffer_idx;i--)
   632 						dl_buffer[i] = dl_buffer[i-1];
   633 					dl_buffer[dl_buffer_idx] = buf[0];
   634 				} else {
   635 					dl_buffer[dl_buffer_len]=buf[0];
   636 					dl_buffer_len++;
   637 					if (dl_buffer_len>1000)
   638 						dl_buffer_len--;
   639 					dl_buffer[dl_buffer_len]='\0';
   640 				}
   641 				dl_buffer_idx++;
   642 				break;
   643 		}
   644 		if (dl_echo) {
   645 			printf("\r%s%s", dl_prompt, dl_buffer);
   646 			printf("\r%s", dl_prompt);
   647 		
   648 			for(i=0;i<dl_buffer_idx;i++)
   649 				printf("%c", dl_buffer[i]);
   650 			fflush(stdout);
   651 		}
   652 	}
   653 
   654 _end:
   655 	cons_set_raw(0);
   656 	if (dl_echo) {
   657 		printf("\r%s%s\n", dl_prompt, dl_buffer);
   658 		fflush(stdout);
   659 	}
   660 
   661 	if (dl_buffer[0]=='!' && dl_buffer[1]=='\0') {
   662 		dl_hist_list();
   663 		return dl_nullstr;
   664 	}
   665 	//write(1,"\n",1);
   666 	return dl_buffer;
   667 }
   668 
   669 #ifndef RADARE_CORE
   670 
   671 
   672 #if __UNIX__
   673 static struct termios tio_old, tio_new;
   674 #include "main.h"
   675 #include <stdarg.h>
   676 #include <termios.h>
   677 #include <sys/ioctl.h>
   678 #include <sys/wait.h>
   679 #include <sys/socket.h>
   680 #endif
   681 
   682 static void cons_set_raw(int b)
   683 {
   684 #if __UNIX__
   685 	if (b) {
   686 		tcgetattr(0, &tio_old);
   687 		memcpy ((char *)&tio_new, (char *)&tio_old, sizeof(struct termios));
   688 		tio_new.c_iflag &= ~(BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
   689 		tio_new.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
   690 		tio_new.c_cflag &= ~(CSIZE|PARENB);
   691 		tio_new.c_cflag |= CS8;
   692 		tio_new.c_cc[VMIN]=1; // Solaris stuff hehe
   693 		tcsetattr(0, TCSANOW, &tio_new);
   694 		fflush(stdout);
   695 		return;
   696 	}
   697 
   698 	tcsetattr(0, TCSANOW, &tio_old);
   699 	fflush(stdout);
   700 #endif
   701 }
   702 
   703 static int cons_get_real_columns()
   704 {
   705 #if __WINDOWS__
   706         return 78;
   707 #endif
   708         struct winsize win;
   709 
   710         if (ioctl(1, TIOCGWINSZ, &win)) {
   711                 /* default values */
   712 //                win.ws_col = 80;
   713  //               win.ws_row = 23;
   714         }
   715 
   716         return win.ws_col;
   717 }
   718 
   719 int main(int argc, const char **argv)
   720 {
   721 	char *ret;
   722 
   723 	dl_histsize = 100;
   724 	dl_prompt = "$ ";
   725 	dl_init();
   726 
   727 	dl_printchar();
   728 
   729 	do {
   730 		ret = dl_readline(argc, argv);
   731 		if (ret) {
   732 			printf(" [line] '%s'\n", ret);
   733 			dl_hist_add(ret);
   734 		}
   735 	} while(ret!=NULL);
   736 	dl_free();
   737 	return 0;
   738 }
   739 
   740 #endif