Equipped frontend_pipes_xorriso.c with word parser code

This commit is contained in:
Thomas Schmitt 2012-09-30 20:34:52 +00:00
parent 3414e4eb78
commit 9367e43923
1 changed files with 495 additions and 21 deletions

View File

@ -1,6 +1,7 @@
/* Beefed-up example from man 2 pipe /* Beefed-up example from man 2 pipe
to illustrate how xorriso is to be used by frontend programs via two pipes. to illustrate how xorriso is to be used by frontend programs via two pipes.
Additionally there is a standalone implementation of Xorriso_parse_line().
Copyright 2012 Thomas Schmitt, <scdbackup@gmx.net> Copyright 2012 Thomas Schmitt, <scdbackup@gmx.net>
Unaltered provided under BSD license. Unaltered provided under BSD license.
@ -11,7 +12,7 @@
cc -g -o frontend_pipes_xorriso frontend_pipes_xorriso.c cc -g -o frontend_pipes_xorriso frontend_pipes_xorriso.c
Usage: Usage:
./frontend_pipes_xorriso [path_to_xorriso_binary] ./frontend_pipes_xorriso [path_to_xorriso_binary | -h]
*/ */
@ -21,11 +22,34 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <ctype.h>
/* Local helpers of parent process */ /* Local helpers of parent process */
int await_all_replies(int fd, char *pending_mark);
int prompt_for_command(char *line, int line_size); struct parse_rules { /* Parsing_parameters. See xorriso.h Xorriso_parse_line */
int do_parse;
char progname[1024];
char prefix[1024];
char separators[256];
int max_words;
int flag;
};
int parse_line(char *progname, char *line,
char *prefix, char *separators, int max_words,
int *argc, char ***argv, int flag);
int dispose_parsed_words(int *argc, char ***argv);
static int await_all_replies(int fd, char *pending_mark,
struct parse_rules *parse);
static int prompt_for_command(char *line, int line_size,
struct parse_rules *parse);
static int usage();
/* Parent and child */ /* Parent and child */
@ -35,8 +59,14 @@ int main(int argc, char *argv[])
pid_t cpid; pid_t cpid;
char *xorriso_path = "/usr/bin/xorriso"; char *xorriso_path = "/usr/bin/xorriso";
if (argc > 1) if (argc > 1) {
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0 ||
strcmp(argv[1], "--help") == 0) {
usage();
exit(0);
}
xorriso_path = argv[1]; xorriso_path = argv[1];
}
if (pipe(command_pipe) == -1) if (pipe(command_pipe) == -1)
{ perror("pipe"); exit(1); } { perror("pipe"); exit(1); }
@ -82,21 +112,25 @@ int main(int argc, char *argv[])
int mark_count = 0, ret; int mark_count = 0, ret;
char pending_mark[16], line[4096]; char pending_mark[16], line[4096];
struct parse_rules parse;
close(command_pipe[0]); /* Close unused read end */ close(command_pipe[0]); /* Close unused read end */
close(reply_pipe[1]); /* Close unused write end */ close(reply_pipe[1]); /* Close unused write end */
memset(&parse, 0, sizeof(parse)); /* Disable parsing as default */
strcpy(parse.progname, argv[0]);
/* Dialog loop */ /* Dialog loop */
sprintf(pending_mark, "%d", mark_count); sprintf(pending_mark, "%d", mark_count);
while (1) { while (1) {
/* Wait for pending mark and print all replies */ /* Wait for pending mark and print all replies */
ret = await_all_replies(reply_pipe[0], pending_mark); ret = await_all_replies(reply_pipe[0], pending_mark, &parse);
if (ret < 0) if (ret < 0)
break; break;
/* Prompt for command line */ /* Prompt for command line */
ret = prompt_for_command(line, sizeof(line)); ret = prompt_for_command(line, sizeof(line), &parse);
if (ret <= 0) if (ret <= 0)
break; break;
@ -130,10 +164,60 @@ int main(int argc, char *argv[])
} }
/* Local helpers of parent process */ /* ------------------- Local helpers of parent process -------------------- */
int await_all_replies(int fd, char *pending_mark) static int usage()
{
static char helptext[][80] = {
"usage: frontend_pipes_xorriso [path_to_xorriso|-h]",
"",
"Forks a process that runs xorriso and communicates with it via two pipes.",
"The command pipe sends payload commands and -mark commands. The reply pipe",
"receives -pkt_output lines which it dispatches to stdout and stderr.",
"The communication between both processes is made synchronous by the parent",
"awaiting the -mark message of the child.",
"Optionally the reply lines can be parsed into words. This is initiated by",
"meta command",
" @parse [prefix [separators [max_words [flag]]]]",
"which sets the four parameters for a function equivalent to",
"Xorriso_parse_line() (see xorriso.h). All reply will then be parsed and",
"non-empty word arrays are displayed. Meta command",
" @noparse",
"ends this mode.",
"@END@"
};
int i;
for (i = 0; strcmp(helptext[i], "@END@") != 0; i++)
fprintf(stderr, "%s\n", helptext[i]);
return(1);
}
static int show_parsed(struct parse_rules *parse, char *line)
{
int argc, ret = 0, i;
char **argv = NULL;
if (!parse->do_parse)
return(2);
ret = parse_line(parse->progname, line, parse->prefix, parse->separators,
parse->max_words, &argc, &argv, parse->flag);
if (ret <= 0 || argc <= 0)
return(0);
fprintf(stderr, "-----------------------------------------------------\n");
fprintf(stderr, "parse_line returns %d, argc = %d\n", ret, argc);
for (i = 0; i < argc; i++)
fprintf(stderr, "%2d : %s\n", i, argv[i]);
fprintf(stderr, "-----------------------------------------------------\n");
dispose_parsed_words(&argc, &argv); /* release memory */
return(1);
}
static int await_all_replies(int fd, char *pending_mark,
struct parse_rules *parse)
{ {
int count, remainder = 0; int count, remainder = 0;
char buf[32769], *line, *npt; char buf[32769], *line, *npt;
@ -206,6 +290,11 @@ int await_all_replies(int fd, char *pending_mark)
*/ */
fprintf(stderr, "%s\n", line); fprintf(stderr, "%s\n", line);
} }
/* Parse line and show words */
if (strlen(line) >= 5)
show_parsed(parse, line + 5);
line = npt + 1; line = npt + 1;
} }
} }
@ -213,23 +302,408 @@ int await_all_replies(int fd, char *pending_mark)
} }
int prompt_for_command(char *line, int line_size) static int input_interpreter(char *line, struct parse_rules *parse)
{ {
int l; int argc, ret = 0;
char **argv = NULL;
ret = parse_line(parse->progname, line, "", "", 6, &argc, &argv, 0);
if (ret <= 0 || argc <= 0)
return(0);
if (strcmp(argv[0], "@parse") == 0) {
parse->do_parse = 1;
parse->prefix[0] = 0;
if (argc > 1)
strcpy(parse->prefix, argv[1]);
parse->separators[0] = 0;
if (argc > 2)
strcpy(parse->separators, argv[2]);
parse->max_words = 0;
if (argc > 3)
sscanf(argv[3], "%d", &(parse->max_words));
parse->max_words = 0;
if (argc > 4)
sscanf(argv[4], "%d", &(parse->flag));
ret = 1;
} else if(strcmp(argv[0], "@noparse") == 0) {
parse->do_parse = 0;
ret = 1;
} else {
ret = 0;
}
dispose_parsed_words(&argc, &argv); /* release memory */
return ret;
}
static int prompt_for_command(char *line, int line_size,
struct parse_rules *parse)
{
int l, ret;
char *line_res; char *line_res;
fprintf(stderr, "+++ Enter a command and its parameters :\n"); while (1) {
line_res = fgets(line, line_size - 1, stdin); fprintf(stderr, "+++ Enter a command and its parameters :\n");
if (line_res == NULL) line_res = fgets(line, line_size - 1, stdin);
return(0); if (line_res == NULL)
l = strlen(line); return(0);
if (l == 0) { l = strlen(line);
line[0] = '\n'; if (l == 0) {
line[1] = 0; line[0] = '\n';
} else if (line[l - 1] != '\n') { line[1] = 0;
line[l] = '\n'; } else if (line[l - 1] != '\n') {
line[l + 1] = 0; line[l] = '\n';
line[l + 1] = 0;
}
/* Interpret meta commands which begin by @ */
ret = input_interpreter(line, parse);
if (ret == 0)
return(1);
if (ret < 0)
return(-1);
} }
}
/* -------- Line-to-word parser equivalent to Xorriso_parse_line() -------- */
static int Sfile_sep_make_argv(char *progname, char *line, char *separators,
int max_words, int *argc, char ***argv, int flag);
int parse_line(char *progname, char *line,
char *prefix, char *separators, int max_words,
int *argc, char ***argv, int flag)
{
int ret, bsl_mode;
char *to_parse;
*argc = 0;
*argv = NULL;
to_parse = line;
bsl_mode = (flag >> 1) & 15;
if (prefix[0]) {
if (strncmp(line, prefix, strlen(prefix)) == 0) {
to_parse = line + strlen(prefix);
} else {
ret = 2; goto ex;
}
}
ret = Sfile_sep_make_argv(progname, to_parse, separators,
max_words, argc, argv,
(!(flag & 32)) | 4 | (bsl_mode << 5));
if (ret < 0) {
fprintf(stderr,
"%s : Severe lack of resources during command line parsing\n",
progname);
goto ex;
}
if (ret == 0) {
fprintf(stderr,
"%s : Incomplete quotation in %s line: %s\n",
progname, (flag & 32) ? "command" : "parsed", to_parse);
goto ex;
}
ex:;
if (ret <= 0)
Sfile_sep_make_argv("", "", "", 0, argc, argv, 2); /* release memory */
return(ret);
}
int dispose_parsed_words(int *argc, char ***argv)
{
Sfile_sep_make_argv("", "", "", 0, argc, argv, 2);
return(1); return(1);
} }
/* -------------- Some helpers copied from xorriso/sfile.c ----------------- */
static int Sfile_destroy_argv(int *argc, char ***argv, int flag)
{
int i;
if(*argc>0 && *argv!=NULL){
for(i=0;i<*argc;i++){
if((*argv)[i]!=NULL)
free((*argv)[i]);
}
free((char *) *argv);
}
*argc= 0;
*argv= NULL;
return(1);
}
/* 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
bit1= allow to convert \000 to binary 0
*/
static int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag)
{
char *rpt, *wpt, num_text[8], 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] <= '7' &&
rpt[1] >= '0' && rpt[1] <= '7' &&
rpt[2] >= '0' && rpt[2] <= '7') {
num_text[0]= '0';
num_text[1]= *(rpt + 0);
num_text[2]= *(rpt + 1);
num_text[3]= *(rpt + 2);
num_text[4]= 0;
sscanf(num_text, "%o", &num);
if((num > 0 || (flag & 2)) && 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);
}
#define SfileadrL 4096
static int Sfile_sep_make_argv(char *progname, char *line, char *separators,
int max_words, int *argc, char ***argv, int flag)
/*
bit0= read progname as first argument from line
bit1= just release argument list argv and return
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
bit7= append a NULL element to argv
*/
{
int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten;
char *cpt,*start;
char *buf= NULL;
Sfile_destroy_argv(argc,argv,0);
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)){
argzaehl= line_start_argc= 1;
if(pass==0)
maxl= strlen(progname);
else
strcpy((*argv)[0],progname);
} else {
argzaehl= line_start_argc= 0;
if(pass==0) maxl= 0;
}
while(*(++cpt)!=0){
if(*separators) {
if(strchr(separators, *cpt) != NULL)
continue;
} else if(isspace(*cpt))
continue;
start= cpt;
buf[0]= 0;
cpt--;
if(max_words > 0 && argzaehl >= max_words && *cpt != 0) {
/* take uninterpreted up to the end */
cpt+= strlen(cpt) - 1;
}
while(*(++cpt)!=0) {
if(*separators) {
if(strchr(separators, *cpt) != NULL)
break;
} else if(isspace(*cpt))
break;
if(*cpt=='"'){
l= cpt-start; bufl= strlen(buf);
if(l>0) {
strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
if(bsl_mode >= 3) {
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)
{ret= 0; goto ex;}
l= cpt-start; bufl= strlen(buf);
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) {
strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
if(bsl_mode >= 3) {
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)
{ret= 0; goto ex;}
l= cpt-start; bufl= strlen(buf);
if(l>0) {
strncat(buf,start,l);buf[bufl+l]= 0;
if(bsl_mode >= 2) {
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) {
strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
if(bsl_mode >= 3) {
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))
if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
l++;
if(l>maxl) maxl= l;
}else{
strcpy((*argv)[argzaehl],buf);
if(argzaehl==line_start_argc && (flag&8))
if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
sprintf((*argv)[argzaehl],"-%s", buf);
}
argzaehl++;
if(*cpt==0) break;
}
if(pass==0){
if(flag & 16)
{ret= 1; goto ex;}
*argc= argzaehl;
if(argzaehl>0 || (flag & 128)) {
*argv= (char **) calloc((argzaehl + !!(flag & 128)), sizeof(char *));
if(*argv==NULL)
{ret= -1; goto ex;}
}
for(i=0;i<*argc;i++) {
(*argv)[i]= (char *) calloc(maxl + 1, 1);
if((*argv)[i]==NULL)
{ret= -1; goto ex;}
}
if(flag & 128)
(*argv)[*argc]= NULL;
}
}
ret= 1;
ex:
if(buf != NULL)
free(buf);
return(ret);
}