diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index 960f8583..d6c3c03a 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH XORRISO 1 "Oct 15, 2008" +.TH XORRISO 1 "Oct 16, 2008" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -2198,6 +2198,34 @@ quotation marks. .br For brevity the list delimiter is referred as "--" throughout this text. .TP +\fB\-backslash_codes\fR "on"|"off"|mode[:mode] +Enable or disable the interpretation of symbolic representations of special +characters with quoted input or with program arguments. If enabled the +following translations apply: +.br + \\a=bell(007) \\b=backspace(008) \\e=Escape(033) \\f=formfeed(014) +.br + \\n=linefeed(012) \\r=carriage_return(015) \\t=tab(011) +.br + \\v=vtab(013) \\\\=backslash(134) \\[0-9][0-9][0-9]=octal_code +.br + \\\\x[0-9a-f][0-9a-f]=hex_code \\cC=control-C +.br +Translations can occur with quoted input in 3 modes: +.br + "in_double_quotes" translates only inside " quotation. +.br + "outside_single_quotes" translates not inside ' quotation. +.br + "with_quoted_input" translates all input text. +.br +With the start program arguments there is mode: +.br + "with_program_arguments" translates all program arguments. +.br +Mode "off" is default and disables any translation. +Mode "on" is the same as "with_quoted_input:with_program_arguments". +.TP \fB\-temp_mem_limit\fR number["k"|"m"] Set the maximum size of temporary memory to be used for image dependent buffering. Currently this applies to pattern expansion only. diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index 065d5827..94b66404 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -513,6 +513,130 @@ int Sfile_destroy_argv(int *argc, char ***argv, int flag) } +/* Converts backslash codes into single characters: + \a BEL 7 , \b BS 8 , \e ESC 27 , \f FF 12 , \n LF 10 , \r CR 13 , + \t HT 9 , \v VT 11 , \\ \ 92 + \[0-9][0-9][0-9] octal code , \x[0-9a-f][0-9a-f] hex code , + \cX control-x (ascii(X)-64) + @param upto maximum number of characters to examine for backslash. + The scope of a backslash (0 to 3 characters) is not affected. + @param eaten returns the difference in length between input and output + @param flag bit0= only determine *eaten, do not convert +*/ +int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag) +{ + char *rpt, *wpt, num_text[4], wdummy[8]; + unsigned int num= 0; + + *eaten= 0; + wpt= text; + for(rpt= text; *rpt != 0 && rpt - text < upto; rpt++) { + if(flag & 1) + wpt= wdummy; + if(*rpt == '\\') { + rpt++; + (*eaten)++; + if(*rpt == 'a') { + *(wpt++)= 7; + } else if(*rpt == 'b') { + *(wpt++)= 8; + } else if(*rpt == 'e') { + *(wpt++)= 27; + } else if(*rpt == 'f') { + *(wpt++)= 12; + } else if(*rpt == 'n') { + *(wpt++)= 10; + } else if(*rpt == 'r') { + *(wpt++)= 13; + } else if(*rpt == 't') { + *(wpt++)= 9; + } else if(*rpt == 'v') { + *(wpt++)= 11; + } else if(*rpt == '\\') { + *(wpt++)= '\\'; + } else if(rpt[0] >= '0' && rpt[0] <= '9' && + rpt[1] >= '0' && rpt[1] <= '9' && + rpt[2] >= '0' && rpt[2] <= '9') { + num_text[0]= *(rpt + 0); + num_text[1]= *(rpt + 1); + num_text[2]= *(rpt + 2); + num_text[3]= 0; + sscanf(num_text, "%o", &num); + if(num > 0 && num <= 255) { + rpt+= 2; + (*eaten)+= 2; + *(wpt++)= num; + } else + goto not_a_code; + } else if(rpt[0] == 'x' && + ((rpt[1] >= '0' && rpt[1] <= '9') || + (rpt[1] >= 'A' && rpt[1] <= 'F') || + (rpt[1] >= 'a' && rpt[1] <= 'f')) + && + ((rpt[2] >= '0' && rpt[2] <= '9') || + (rpt[2] >= 'A' && rpt[2] <= 'F') || + (rpt[2] >= 'a' && rpt[2] <= 'f')) + ) { + num_text[0]= *(rpt + 1); + num_text[1]= *(rpt + 2); + num_text[2]= 0; + sscanf(num_text, "%x", &num); + if(num > 0 && num <= 255) { + rpt+= 2; + (*eaten)+= 2; + *(wpt++)= num; + } else + goto not_a_code; + } else if(*rpt == 'c') { + if(rpt[1] > 64 && rpt[1] < 96) { + *(wpt++)= rpt[1] - 64; + rpt++; + (*eaten)++; + } else + goto not_a_code; + } else { +not_a_code:; + *(wpt++)= '\\'; + rpt--; + (*eaten)--; + } + } else + *(wpt++)= *rpt; + } + *wpt= *rpt; + return(1); +} + + +int Sfile_argv_bsl(int argc, char ***argv, int flag) +{ + int i, ret, eaten; + char **new_argv= NULL; + + if(argc <= 0) + return(0); + new_argv= (char **) Smem_malloC(argc * sizeof(char *)); + if(new_argv == NULL) + return(-1); + for(i= 0; i < argc; i++) { + new_argv[i]= strdup((*argv)[i]); + if(new_argv[i] == NULL) + {ret= -1; goto ex;} + ret= Sfile_bsl_interpreter(new_argv[i], strlen(new_argv[i]), &eaten, 0); + if(ret <= 0) + goto ex; + } + ret= 1; +ex:; + if(ret <= 0) { + if(new_argv != NULL) + free((char *) new_argv); + } else + *argv= new_argv; + return(ret); +} + + int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, int flag) /* @@ -521,18 +645,29 @@ int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, bit2= abort with return(0) if incomplete quotes are found bit3= eventually prepend missing '-' to first argument read from line bit4= like bit2 but only check quote completeness, do not allocate memory +>>> + bit5+6= interpretation of backslashes: + 0= no interpretation, leave unchanged + 1= only inside double quotes + 2= outside single quotes + 3= everywhere */ { - int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc; + int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten; char *cpt,*start; - char buf[SfileadrL]; + char *buf= NULL; Sfile_destroy_argv(argc,argv,0); - if(flag&2) return(1); + if(flag&2) + {ret= 1; goto ex;} if(flag & 16) flag|= 4; + bsl_mode= (flag >> 5) & 3; + buf= calloc(strlen(line) + SfileadrL, 1); + if(buf == NULL) + {ret= -1; goto ex;} for(pass=0;pass<2;pass++) { cpt= line-1; if(!(flag&1)){ @@ -554,32 +689,68 @@ int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, if(isspace(*cpt)) break; if(*cpt=='"'){ l= cpt-start; bufl= strlen(buf); - if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;} + if(l>0) { + strncpy(buf + bufl, start, l); buf[bufl + l]= 0; + if(bsl_mode >= 2) { + ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } l= strlen(buf); start= cpt+1; while(*(++cpt)!=0) if(*cpt=='"') break; if((flag&4) && *cpt==0) - return(0); + {ret= 0; goto ex;} l= cpt-start; bufl= strlen(buf); - if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;} + if(l>0) { + strncpy(buf + bufl, start, l); + buf[bufl + l]= 0; + if(bsl_mode >= 1) { + ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } start= cpt+1; }else if(*cpt=='\''){ l= cpt-start; bufl= strlen(buf); - if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;} + if(l>0) { + strncpy(buf + bufl, start, l); buf[bufl + l]= 0; + if(bsl_mode >= 2) { + ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } l= strlen(buf); start= cpt+1; while(*(++cpt)!=0) if(*cpt=='\'') break; if((flag&4) && *cpt==0) - return(0); + {ret= 0; goto ex;} l= cpt-start; bufl= strlen(buf); - if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;} + if(l>0) { + strncat(buf,start,l);buf[bufl+l]= 0; + if(bsl_mode >= 3) { + ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } start= cpt+1; } if(*cpt==0) break; } l= cpt-start; bufl= strlen(buf); - if(l>0) {strncat(buf,start,l);buf[bufl+l]= 0;} + if(l>0) { + strncpy(buf + bufl, start, l); buf[bufl + l]= 0; + if(bsl_mode >= 2) { + ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); + if(ret <= 0) + goto ex; + } + } l= strlen(buf); if(pass==0){ if(argzaehl==line_start_argc && (flag&8)) @@ -597,21 +768,25 @@ int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, } if(pass==0){ if(flag & 16) - return(1); + {ret= 1; goto ex;} *argc= argzaehl; if(argzaehl>0) { *argv= (char **) Smem_malloC(argzaehl*sizeof(char *)); if(*argv==NULL) - return(-1); + {ret= -1; goto ex;} } for(i=0;i<*argc;i++) { (*argv)[i]= (char *) Smem_malloC((maxl+1)); if((*argv)[i]==NULL) - return(-1); + {ret= -1; goto ex;} } } } - return(1); + ret= 1; +ex: + if(buf != NULL) + free(buf); + return(ret); } @@ -3405,6 +3580,7 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->do_concat_split= 1; m->do_auto_chmod= 0; m->dialog= 0; + m->bsl_interpretation= 0; m->search_mode= 0; m->structured_search= 1; m->do_iso_rr_pattern= 1; @@ -3837,6 +4013,7 @@ klammer_affe:; bit1= release allocated memory and return 1 bit2= with bit0: warn of empty text arguments bit3= deliver as single quoted text including all whitespace + and without any backslash interpretation @return -1=out of memory , 0=line format error , 1=ok, go on , 2=done */ int Xorriso_read_lines(struct XorrisO *xorriso, FILE *fp, int *linecount, @@ -3894,7 +4071,8 @@ int Xorriso_read_lines(struct XorrisO *xorriso, FILE *fp, int *linecount, linept= line + base_length; } if((flag & 1) && !(flag & 8)) { - ret= Sfile_make_argv("", line, argc, argv, 1); + ret= Sfile_make_argv("", line, argc, argv, + 1 | ((xorriso->bsl_interpretation & 3) << 5)); if(ret < 0) return(ret); if(flag & 4) @@ -3970,7 +4148,8 @@ int Xorriso_pager(struct XorrisO *xorriso, char *line, int flag) int ret,linecount; char info_text[10*SfileadrL]; - if(xorriso->result_page_length<=0 || xorriso->request_not_to_ask) + if(xorriso->result_page_length<=0 || xorriso->request_not_to_ask || + xorriso->dialog == 0) return(1); Xorriso_predict_linecount(xorriso,line,&linecount,0); if(xorriso->result_line_counter+linecount>xorriso->result_page_length) { @@ -5082,6 +5261,29 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag) if(!(is_default && no_defaults)) Xorriso_status_result(xorriso,filter,fp,flag&2); + is_default= (xorriso->bsl_interpretation == 0); + strcpy(line, "-backslash_codes "); + if(xorriso->bsl_interpretation == 0) + strcat(line, "off"); + else if(xorriso->bsl_interpretation == (3 | 16)) + strcat(line, "on"); + else { + if((xorriso->bsl_interpretation & 3) == 1) + strcat(line, "in_double_quotes"); + else if((xorriso->bsl_interpretation & 3) == 2) + strcat(line, "outside_single_quotes"); + else if((xorriso->bsl_interpretation & 3) == 3) + strcat(line, "with_quoted_input"); + if(xorriso->bsl_interpretation & 16) { + if(strlen(line) > 17) + strcat(line, ":"); + strcat(line, "with_program_arguments"); + } + } + strcat(line, "\n"); + if(!(is_default && no_defaults)) + Xorriso_status_result(xorriso,filter,fp,flag&2); + is_default= !xorriso->packet_output; sprintf(line,"-pkt_output %s\n",(xorriso->packet_output?"on":"off")); if(!(is_default && no_defaults)) @@ -9987,6 +10189,50 @@ ex:; } +/* Option -backslash_codes */ +int Xorriso_option_backslash_codes(struct XorrisO *xorriso, char *mode, + int flag) +{ + char *npt, *cpt; + int l, was; + + was= xorriso->bsl_interpretation; + xorriso->bsl_interpretation= 0; + npt= cpt= mode; + for(; npt!=NULL; cpt= npt+1) { + npt= strchr(cpt,':'); + if(npt==NULL) + l= strlen(cpt); + else + l= npt-cpt; + if(l == 0) + continue; + if(l == 3 && strncmp(cpt, "off", l)==0) { + xorriso->bsl_interpretation= 0; + } else if(l == 16 && strncmp(cpt, "in_double_quotes", l)==0) { + xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 1; + } else if(l == 21 && strncmp(cpt, "outside_single_quotes", l)==0) { + xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 2; + } else if(l == 17 && strncmp(cpt, "with_quoted_input", l)==0) { + xorriso->bsl_interpretation= (xorriso->bsl_interpretation & ~3) | 3; + } else if(l == 22 && strncmp(cpt, "with_program_arguments", l)==0) { + xorriso->bsl_interpretation= xorriso->bsl_interpretation | 16; + } else if(l == 2 && strncmp(cpt, "on", l)==0) { + xorriso->bsl_interpretation= 3 | 16; + } else { + if(linfo_text, "-backslash_codes: unknown mode '%s'", cpt); + else + sprintf(xorriso->info_text, + "-backslash_codes: oversized mode parameter (%d)", l); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + xorriso->bsl_interpretation= was; + return(0); + } + } + return(1); +} + /* Option -ban_stdio_write */ int Xorriso_option_ban_stdio_write(struct XorrisO *xorriso, int flag) @@ -12132,6 +12378,11 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " -history text Copy text into libreadline history. This command", " itself is not copied to the history list.", #endif /* Xorriso_with_readlinE */ +" -backslash_codes \"on\"|\"off\"|\"in_double_quotes\"|", +" \"outside_single_quotes\"|\"with_quoted_input\"", +" [:\"with_program_arguments\"]", +" Disable or enable interpretation of \\a \\b \\e \\f \\n \\r \\t \\v", +" \\\\ \\NNN \\xNN \\cC in input or program arguments.", " -pkt_output \"on\"|\"off\" Direct output to stdout and prefix each line", " by a short header which tells channel id and a mode number.", " Each such output packet is finalized by a newline.", @@ -13060,7 +13311,7 @@ return: <=0 error , 1 = success , 3 = end program run */ { - int ret,linecount= 0, argc, was_failure= 0, fret; + int ret,linecount= 0, argc= 0, was_failure= 0, fret; FILE *fp= NULL; char shellsafe[5*SfileadrL]; char **argv= NULL; @@ -13092,11 +13343,11 @@ return: continue; if(flag&1) { - ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv, 4|8); + ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv, + 4 | 8 | ((xorriso->bsl_interpretation & 3) << 5)); if(ret<=0) goto problem_handler; ret= Xorriso_prescan_args(xorriso,argc,argv,1); - Sfile_make_argv("", "", &argc, &argv, 2); /* release memory */ if(ret==0) {ret= 3; goto ex;} if(ret<0) @@ -13123,6 +13374,7 @@ problem_handler:; } ret= 1; ex:; + Sfile_make_argv("", "", &argc, &argv, 2); /* release memory */ Xorriso_read_lines(xorriso, fp, &linecount, &linec, &linev, 2); Xorriso_reset_counters(xorriso,0); if(fp!=NULL) @@ -14197,7 +14449,8 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, "" }; static char arg1_commands[][40]= { - "abort_on","add_plainly","blank","cd","cdi","cdx","close","commit_eject", + "abort_on","add_plainly","backslash_codes","blank", + "cd","cdi","cdx","close","commit_eject", "dev", "dummy","dialog","disk_pattern","eject","iso_rr_pattern","follow", "format","fs","gid","grow_blindly", "history","indev","joliet","list_delimiter","mark","not_leaf", @@ -14280,16 +14533,16 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, } +/* @param flag bit0= recursion + bit1= these are command line arguments + (for xorriso->argument_emulation) +*/ int Xorriso_interpreter(struct XorrisO *xorriso, int argc, char **argv, int *idx, int flag) /* return: <=0 error , 1 = success , 2 = problem event ignored , 3 = end program run */ -/* - bit0= recursion - bit1= these are command line arguments (for xorriso->argument_emulation) -*/ { int ret, was_dashed, end_ret, num1, num2; char *cmd, *original_cmd, cmd_data[2*SfileadrL], *arg1, *arg2; @@ -14370,6 +14623,10 @@ next_command:; } else if(strcmp(cmd,"as")==0) { ret= Xorriso_option_as(xorriso, argc, argv, idx, 0); + } else if(strcmp(cmd,"backslash_codes")==0) { + (*idx)++; + ret= Xorriso_option_backslash_codes(xorriso, arg1, 0); + } else if(strcmp(cmd,"ban_stdio_write")==0) { ret= Xorriso_option_ban_stdio_write(xorriso, 0); @@ -14908,7 +15165,8 @@ int Xorriso_execute_option(struct XorrisO *xorriso, char *line, int flag) tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec); /* parse line into args */ - ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv, 4); + ret= Sfile_make_argv(xorriso->progname, line, &argc, &argv, + 4 | ((xorriso->bsl_interpretation & 3) << 5)); if(ret < 0) { Xorriso_msgs_submit(xorriso, 0, "Severe lack of resources during command line parsing", 0, "FATAL", 0); @@ -15021,6 +15279,7 @@ int Xorriso_prescan_args(struct XorrisO *xorriso, int argc, char **argv, { int i, ret, was_dashed, num2, arg_count; int was_report_about= 0, was_abort_on= 0, was_return_with= 0; + int was_backslash_codes= 0; char *cmd, *original_cmd, cmd_data[5*SfileadrL], *arg1, *arg2; char mem_list_delimiter[81]; @@ -15103,11 +15362,18 @@ protect_stdout:; goto protect_stdout; } else if(strcmp(cmd, "list_delimiter") == 0) { + /* Needed for interpreting other args. Gets reset after prescan. */ i++; ret= Xorriso_option_list_delimiter(xorriso, arg1, 0); if(ret <= 0) goto ex; + } else if(strcmp(cmd,"backslash_codes")==0) { + i++; + if(!was_backslash_codes) + Xorriso_option_backslash_codes(xorriso, arg1, 0); + was_backslash_codes= 1; + } else { ret= Xorriso_count_args(xorriso, argc-i, argv+i, &arg_count, 1); if(ret==1) @@ -15222,6 +15488,8 @@ int Xorriso_main(int argc, char **argv) } /* Interpret program arguments */ + if(xorriso->bsl_interpretation & 16) + Sfile_argv_bsl(argc, &argv, 0); /* apply Sfile_bsl_interpreter() to args */ i= 1; ret= Xorriso_interpreter(xorriso,argc,argv,&i,2); if(ret==3) diff --git a/xorriso/xorriso.h b/xorriso/xorriso.h index d1cfbfd5..82ca6206 100644 --- a/xorriso/xorriso.h +++ b/xorriso/xorriso.h @@ -282,6 +282,17 @@ int Xorriso_option_alter_date(struct XorrisO *xorriso, char *time_type, char *timestring, int argc, char **argv, int *idx, int flag); +/* Option -as */ +/* @param flag bit0=do not report the added item + bit1=do not reset pacifier, no final pacifier message +*/ +int Xorriso_option_as(struct XorrisO *xorriso, int argc, char **argv, + int *idx, int flag); + +/* Option -backslash_codes */ +int Xorriso_option_backslash_codes(struct XorrisO *xorriso, char *mode, + int flag); + /* Option -ban_stdio_write */ int Xorriso_option_ban_stdio_write(struct XorrisO *xorriso, int flag); diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index 98e0d1b3..41f624d9 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -209,6 +209,16 @@ struct XorrisO { /* the global context of xorriso */ int dialog; /* 0=off , 1=single-line , 2=multi-line */ + int bsl_interpretation; + /* whether to run input through Sfile_bsl_interpreter(): + bit0-1= dialog and quoted file reading + 0= no interpretation, leave unchanged + 1= only inside double quotes + 2= outside single quotes + 3= everywhere + bit2-3= reserved as future expansion of bit0-1 + bit4= interpretation within program start arguments + */ /* Pattern matching facility. It still carries legacy from scdbackup/askme.c but is fully functional for xorriso. diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 033fe1ce..dbd79d97 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.10.15.182605" +#define Xorriso_timestamP "2008.10.17.074953"