You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4569 lines
138 KiB
4569 lines
138 KiB
|
|
/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images. |
|
|
|
Copyright 2007-2015 Thomas Schmitt, <scdbackup@gmx.net> |
|
|
|
Provided under GPL version 2 or later. |
|
|
|
This file contains the implementation of text i/o functions. |
|
*/ |
|
|
|
#ifdef HAVE_CONFIG_H |
|
#include "../config.h" |
|
#endif |
|
|
|
#include <ctype.h> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <sys/stat.h> |
|
#include <sys/time.h> |
|
#include <time.h> |
|
#include <errno.h> |
|
#include <signal.h> |
|
#include <pthread.h> |
|
#include <fcntl.h> |
|
|
|
/* O_BINARY is needed for Cygwin but undefined elsewhere */ |
|
#ifndef O_BINARY |
|
#define O_BINARY 0 |
|
#endif |
|
|
|
|
|
/* for -charset */ |
|
#include <iconv.h> |
|
#include <langinfo.h> |
|
#include <locale.h> |
|
|
|
|
|
#ifdef Xorriso_with_readlinE |
|
#ifdef Xorriso_with_old_readlinE |
|
#include <readline.h> |
|
#include <history.h> |
|
#else /* Xorriso_with_old_readlinE */ |
|
#include <readline/readline.h> |
|
#include <readline/history.h> |
|
#endif /* ! Xorriso_with_old_readlinE */ |
|
#define Xorriso_with_line_editoR yes |
|
#endif /* Xorriso_with_readlinE */ |
|
|
|
#ifdef Xorriso_with_editlinE |
|
#include <histedit.h> |
|
#define Xorriso_with_line_editoR yes |
|
#endif /* Xorriso_with_editlinE */ |
|
|
|
|
|
#include "xorriso.h" |
|
#include "xorriso_private.h" |
|
#include "xorrisoburn.h" |
|
|
|
|
|
int Xorriso_protect_stdout(struct XorrisO *xorriso, int flag) |
|
{ |
|
if(xorriso->dev_fd_1>=0) |
|
return(2); |
|
xorriso->dev_fd_1= dup(1); |
|
close(1); |
|
dup2(2,1); |
|
return(1); |
|
} |
|
|
|
#ifdef Xorriso_with_editlinE |
|
|
|
/* These have to be global and shared by all XorrisOs which might be active. |
|
*/ |
|
static EditLine *editline_handle= NULL; |
|
static History *editline_history= NULL; |
|
static int editline_is_initialized= 0; |
|
|
|
|
|
char *Xorriso__editline_prompt(EditLine *el_handle) |
|
{ |
|
return ""; |
|
} |
|
|
|
|
|
void Xorriso_init_editline(struct XorrisO *xorriso, int flag) |
|
{ |
|
HistEvent ev; |
|
|
|
/* >>> Need mutex */ |
|
|
|
if(editline_is_initialized != 0) |
|
return; |
|
editline_is_initialized= -1; /* Invalid */ |
|
|
|
editline_handle= el_init(xorriso->progname, stdin, stdout, stderr); |
|
if(editline_handle == NULL) |
|
return; |
|
el_set(editline_handle, EL_EDITOR, "emacs"); |
|
el_set(editline_handle, EL_PROMPT, &Xorriso__editline_prompt); |
|
|
|
editline_history= history_init(); |
|
if(editline_history == NULL) |
|
return; |
|
history(editline_history, &ev, H_SETSIZE, 1000); |
|
el_set(editline_handle, EL_HIST, history, editline_history); |
|
|
|
editline_is_initialized= 1; /* Valid now */ |
|
return; |
|
} |
|
|
|
|
|
int Xorriso__shutdown_editline(int flag) |
|
{ |
|
if(editline_history != NULL) |
|
history_end(editline_history); |
|
editline_history= NULL; |
|
if(editline_handle != NULL) |
|
el_end(editline_handle); |
|
editline_handle= NULL; |
|
editline_is_initialized= 0; |
|
return(1); |
|
} |
|
|
|
#endif /* Xorriso_with_editlinE */ |
|
|
|
#ifdef Xorriso_with_readlinE |
|
|
|
/* http://lists.gnu.org/archive/html/bug-readline/2014-06/msg00005.html */ |
|
const char *Xorriso__readline_license(int flag) |
|
{ |
|
#ifdef RL_VERSION_MAJOR |
|
#if RL_VERSION_MAJOR > 5 |
|
|
|
return("GPLv3+"); |
|
|
|
#endif |
|
#endif |
|
|
|
return("GPLv2+"); |
|
} |
|
|
|
#endif /* Xorriso_with_readlinE */ |
|
|
|
#ifdef Xorriso_with_line_editoR |
|
|
|
char *Xorriso_emul_readline(struct XorrisO *xorriso, int flag) |
|
{ |
|
|
|
#ifdef Xorriso_with_editlinE |
|
|
|
const char *cpt; |
|
int count= 0; |
|
char *retpt; |
|
|
|
/* >>> Need mutex */ |
|
|
|
Xorriso_init_editline(xorriso, 0); |
|
if(editline_is_initialized < 0) { |
|
|
|
/* >>> fallback */; |
|
|
|
} |
|
|
|
cpt= el_gets(editline_handle, &count); |
|
if(count == -1 || cpt == NULL) |
|
return(NULL); |
|
retpt= calloc(1, count + 1); |
|
if(retpt == NULL) |
|
return(NULL); |
|
memcpy(retpt, cpt, count); |
|
retpt[count]= 0; |
|
return(retpt); |
|
|
|
#else |
|
|
|
#ifdef Xorriso_with_readlinE |
|
|
|
char *cpt; |
|
|
|
cpt= readline(""); |
|
return(cpt); |
|
|
|
#else |
|
|
|
return(NULL); |
|
|
|
#endif /* ! Xorriso_with_readlinE */ |
|
#endif /* ! Xorriso_with_editlinE */ |
|
} |
|
|
|
|
|
void Xorriso_emul_add_history(struct XorrisO *xorriso, char *line, int flag) |
|
{ |
|
#ifdef Xorriso_with_editlinE |
|
|
|
HistEvent ev; |
|
|
|
/* >>> Need mutex */ |
|
|
|
Xorriso_init_editline(xorriso, 0); |
|
if(editline_is_initialized < 0) |
|
return; |
|
|
|
history(editline_history, &ev, H_ENTER, line); |
|
|
|
#else |
|
|
|
#ifdef Xorriso_with_readlinE |
|
|
|
add_history(line); |
|
|
|
#else |
|
|
|
/* ??? How to raise protest ? */; |
|
|
|
#endif /* ! Xorriso_with_readlinE */ |
|
#endif /* ! Xorriso_with_editlinE */ |
|
} |
|
|
|
|
|
/* @param flag bit1= do only report to fp |
|
*/ |
|
int Xorriso_status_history(struct XorrisO *xorriso, char *filter, FILE *fp, |
|
int flag) |
|
{ |
|
|
|
#ifdef Xorriso_with_editlinE |
|
|
|
int ret, l; |
|
HistEvent ev; |
|
int hc, i, was_end= 0; |
|
char *str= NULL; |
|
|
|
|
|
/* >>> Need mutex */ |
|
|
|
Xorriso_init_editline(xorriso, 0); |
|
if(editline_is_initialized < 0) |
|
{ret= 0; goto ex;} |
|
|
|
Xorriso_alloc_meM(str, char, SfileadrL); |
|
|
|
ret= history(editline_history, &ev, H_LAST); |
|
for(hc= 0; ret != -1; hc++) { |
|
ret= history(editline_history, &ev, H_PREV); |
|
was_end = (strcmp(ev.str, "-end") == 0); |
|
} |
|
if(was_end) |
|
hc--; |
|
if(hc >= xorriso->status_history_max) |
|
i= hc - xorriso->status_history_max; |
|
else |
|
i= 0; |
|
|
|
ret= history(editline_history, &ev, H_LAST); |
|
for(; i < hc && ret != -1; i++) { |
|
/* Eat newline at line end */ |
|
strncpy(str, ev.str, SfileadrL - 1); |
|
str[SfileadrL - 1]= 0; |
|
l= strlen(str); |
|
if(l > 0) |
|
if(str[l - 1] == '\n') |
|
str[l - 1]= 0; |
|
|
|
sprintf(xorriso->result_line, "-history "); |
|
Text_shellsafe(str, xorriso->result_line, 1); |
|
strcat(xorriso->result_line, "\n"); |
|
Xorriso_status_result(xorriso, filter, fp, flag & 2); |
|
ret= history(editline_history, &ev, H_PREV); |
|
} |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(str); |
|
return(ret); |
|
|
|
#else |
|
#ifdef Xorriso_with_readlinE |
|
|
|
HIST_ENTRY **hl; |
|
int hc, i; |
|
|
|
hl= history_list(); |
|
if(hl != NULL) { |
|
for(hc= 0; hl[hc] != NULL; hc++); |
|
if(hc > 0) |
|
if(strcmp(hl[hc-1]->line, "-end") == 0) |
|
hc--; |
|
if(hc >= xorriso->status_history_max) |
|
i= hc - xorriso->status_history_max; |
|
else |
|
i= 0; |
|
for(; i < hc; i++) { |
|
sprintf(xorriso->result_line, "-history "); |
|
Text_shellsafe(hl[i]->line, xorriso->result_line, 1); |
|
strcat(xorriso->result_line, "\n"); |
|
Xorriso_status_result(xorriso, filter, fp, flag & 2); |
|
} |
|
} |
|
return(1); |
|
|
|
#else /* Xorriso_with_readlinE */ |
|
|
|
return(0); |
|
|
|
#endif /* ! Xorriso_with_readlinE */ |
|
#endif /* ! Xorriso_with_editlinE */ |
|
|
|
} |
|
|
|
#endif /* Xorriso_with_line_editoR */ |
|
|
|
|
|
int Xorriso_dialog_input(struct XorrisO *xorriso, char line[], int linesize, |
|
int flag) |
|
/* |
|
bit0= do not write to history |
|
bit1= do not read input (but eventually write to history) |
|
bit2= do not write to history line which begin with "-history:" or "-history " |
|
bit3= enforce single line dialog mode |
|
bit4= do not read from xorriso->buffered_dialog |
|
bit5= write to history in any case (if it is enabled at compile time) |
|
*/ |
|
{ |
|
char *cpt= NULL, **argv= NULL, *linept, *why_append= ""; |
|
int ret, argc= 0, base_length= 0, l, append_line; |
|
#ifdef Xorriso_with_line_editoR |
|
static char last_input[SfileadrL]= {""}; |
|
int no_history= 0; |
|
#endif /* Xorriso_with_line_editoR */ |
|
double tdiff; |
|
struct timeval tv; |
|
struct timezone tz; |
|
struct Xorriso_lsT *next_lst; |
|
|
|
gettimeofday(&tv,&tz); |
|
tdiff= tv.tv_sec+(1.e-6*(double) tv.tv_usec); |
|
|
|
fflush(stdout); |
|
linept= line; |
|
|
|
#ifdef Xorriso_with_line_editoR |
|
no_history= (flag & 1) || xorriso->use_stdin; |
|
#endif |
|
|
|
get_single:; |
|
|
|
if(xorriso->buffered_dialog != NULL && !(flag & 16)) { |
|
/* Consume next buffered line */ |
|
next_lst= Xorriso_lst_get_next(xorriso->buffered_dialog, 0); |
|
strcpy(line, Xorriso_lst_get_text(xorriso->buffered_dialog, 0)); |
|
Xorriso_lst_destroy(&(xorriso->buffered_dialog), 0); |
|
xorriso->buffered_dialog= next_lst; |
|
goto process_single; |
|
} |
|
|
|
#ifdef Xorriso_with_line_editoR |
|
|
|
if(xorriso->use_stdin || xorriso->dev_fd_1>=0 || |
|
xorriso->tolerate_stdin_eof) { |
|
if(flag&2) { |
|
if(flag & 32) |
|
goto put_into_history; |
|
{ret= 1; goto ex;} |
|
} |
|
if(Sfile_fgets_n(linept,linesize - base_length - 1, stdin, |
|
(xorriso->dialog == 2)) == NULL) { |
|
if(xorriso->tolerate_stdin_eof) |
|
{ret= -2; goto ex;} |
|
/* need a very dramatic end */ |
|
kill(getpid(),SIGHUP); |
|
{ret= -1; goto ex;} |
|
} |
|
goto process_single; |
|
} |
|
if(flag&2) { |
|
cpt= NULL; |
|
} else { |
|
cpt= Xorriso_emul_readline(xorriso, 0); |
|
if(cpt==NULL) { |
|
/* need a very dramatic end */ |
|
kill(getpid(),SIGHUP); |
|
{ret= -1; goto ex;} |
|
} |
|
l= strlen(cpt); |
|
if(l >= linesize - base_length - 1) { |
|
strncpy(linept, cpt, linesize - 1); |
|
line[linesize - 1]= 0; |
|
sprintf(xorriso->info_text,"Input line too long !"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); |
|
goto new_empty; |
|
} else |
|
strcpy(linept, cpt); |
|
} |
|
|
|
#else /* Xorriso_with_line_editoR */ |
|
|
|
if(flag&2) |
|
{ret= 1; goto ex;} |
|
if(Sfile_fgets_n(linept, linesize - base_length - 1, stdin, |
|
(xorriso->dialog == 2)) == NULL) { |
|
if(xorriso->tolerate_stdin_eof) |
|
{ret= -2; goto ex;} |
|
/* need a very dramatic end */ |
|
kill(getpid(),SIGHUP); |
|
{ret= -1; goto ex;} |
|
} |
|
|
|
#endif /* ! Xorriso_with_line_editoR */ |
|
|
|
process_single:; |
|
|
|
if(xorriso->dialog == 2 && !(flag & 8)) { |
|
append_line= 0; |
|
if(linept != line && strcmp(linept, "@@@") == 0) { |
|
sprintf(xorriso->info_text, "Incomplete input line cleared by %s", |
|
linept); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0); |
|
new_empty:; |
|
line[0]= 0; |
|
linept= line; |
|
sprintf(xorriso->info_text, "-------------------------------------\n"); |
|
Xorriso_info(xorriso,0); |
|
sprintf(xorriso->info_text, "Enter new text for empty input line :\n"); |
|
Xorriso_info(xorriso,0); |
|
goto get_single; |
|
} |
|
l= strlen(line); |
|
ret= Sfile_make_argv("", line, &argc, &argv, 16); |
|
if(ret < 0) |
|
goto ex; |
|
if(ret == 0 && !append_line) { |
|
/* append a newline character */ |
|
if(l >= linesize - 1) { |
|
sprintf(xorriso->info_text,"Input line too long !"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); |
|
goto new_empty; |
|
} |
|
line[l]= '\n'; |
|
line[l + 1]= 0; |
|
append_line= 1; |
|
why_append= "Quoted newline char"; |
|
} |
|
if(l > 0 && !append_line) |
|
if(line[l - 1] == '\\') { |
|
line[l - 1]= 0; |
|
append_line= 1; |
|
why_append= "Trailing backslash "; |
|
} |
|
if(append_line) { |
|
base_length= strlen(line); |
|
linept= line + base_length; |
|
sprintf(xorriso->info_text, |
|
"---------------------------------------------------------------\n"); |
|
Xorriso_info(xorriso,0); |
|
sprintf(xorriso->info_text, |
|
"%s : Enter rest of line (or @@@ to clear it) :\n", why_append); |
|
Xorriso_info(xorriso,0); |
|
goto get_single; |
|
} |
|
} |
|
|
|
#ifdef Xorriso_with_line_editoR |
|
|
|
put_into_history:; |
|
if((flag & 32) || (line[0]!=0 && strcmp(last_input,line)!=0 && !no_history)) { |
|
if(!((flag&4) && |
|
(strncmp(line,"-history:",9)==0 || strncmp(line,"-history ",9)==0))) { |
|
Xorriso_emul_add_history(xorriso, line, 0); |
|
strncpy(last_input,line,sizeof(last_input)-1); |
|
last_input[sizeof(last_input)-1]= 0; |
|
} |
|
} |
|
|
|
#endif /* Xorriso_with_line_editoR */ |
|
|
|
ret= 1; |
|
ex:; |
|
if(cpt!=NULL) |
|
free(cpt); |
|
gettimeofday(&tv,&tz); |
|
xorriso->idle_time+= tv.tv_sec+(1.e-6*(double) tv.tv_usec)-tdiff; |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_request_confirmation(struct XorrisO *xorriso, int flag) |
|
/* |
|
bit0= important operation going on: |
|
demand confirmation of abort, only abort on @@@ |
|
bit1= mark '@' and '@@' by return 4 |
|
bit2= accept: i|n= ignore | do not remove , r|y= retry | remove , q|x= abort |
|
bit3= @@@ = 'done reading' rather than 'abort' |
|
bit4= in non-dialog mode return 6 rather than 1 |
|
*/ |
|
/* return: <=0 error |
|
1= go on | do not remove existing file |
|
2= abort |
|
3= redo request for confirmation |
|
4= see flag bit1 |
|
(5= skip volume) |
|
6= retry failed operation | remove existing file |
|
*/ |
|
{ |
|
int ret; |
|
char *line= NULL, *cpt, *previous_line= NULL; |
|
char *abort_req_text,*abort_really_text; |
|
|
|
Xorriso_alloc_meM(line, char, SfileadrL); |
|
Xorriso_alloc_meM(previous_line, char, SfileadrL); |
|
|
|
if(!xorriso->dialog) { |
|
if(flag&16) |
|
{ret= 6; goto ex;} |
|
{ret= 1; goto ex;} |
|
} |
|
if(flag&8) { |
|
abort_req_text= "request to end"; |
|
abort_really_text= "done reading"; |
|
} else { |
|
abort_req_text= "request to abort"; |
|
abort_really_text= "abort this command"; |
|
} |
|
ret= Xorriso_dialog_input(xorriso,line, SfileadrL, 1); |
|
xorriso->result_line_counter= 0; |
|
xorriso->result_page_counter++; |
|
if(ret<=0) |
|
if(xorriso->result_page_length>0) |
|
xorriso->result_page_length= -xorriso->result_page_length; |
|
|
|
cpt= line; |
|
if(strcmp(cpt,"@@@")==0 || |
|
strcmp(cpt,"x")==0 || strcmp(cpt,"X")==0 || |
|
strcmp(cpt,"q")==0 || strcmp(cpt,"Q")==0) { |
|
if(flag&1) { |
|
strcpy(previous_line,cpt); |
|
sprintf(xorriso->info_text, |
|
"... [%s = %s registered. Really %s ? (y/n) ] ...\n", |
|
cpt,abort_req_text,abort_really_text); |
|
Xorriso_info(xorriso,0); |
|
ret= Xorriso_dialog_input(xorriso,line, SfileadrL, 1); |
|
if(ret<=0) |
|
goto ex; |
|
cpt= line; |
|
if(strcmp(cpt,previous_line)==0 || |
|
((*cpt=='Y' || *cpt=='y' || *cpt=='j' || *cpt=='J' || *cpt=='1') && |
|
*(cpt+1)==0)) { |
|
xorriso->request_to_abort= 1; |
|
sprintf(xorriso->info_text, |
|
"------- ( %s confirmed )\n",abort_req_text); |
|
Xorriso_info(xorriso,0); |
|
{ret= 2; goto ex;} |
|
} |
|
sprintf(xorriso->info_text, "....... ( %s revoked )\n",abort_req_text); |
|
Xorriso_info(xorriso,0); |
|
{ret= 3; goto ex;} |
|
} |
|
xorriso->request_to_abort= 1; |
|
sprintf(xorriso->info_text, |
|
"----------- [%s = request to abort registered. Operation ends ] ------------\n", |
|
cpt); |
|
Xorriso_info(xorriso,0); |
|
{ret= 2; goto ex;} |
|
} else if(*cpt=='@') { |
|
if(strcmp(cpt,"@@")==0) { |
|
goto klammer_affe; |
|
|
|
} else if(strcmp(cpt,"@")==0) { |
|
klammer_affe:; |
|
if(xorriso->result_page_length>0) |
|
xorriso->result_page_length= -xorriso->result_page_length; |
|
if(flag&1) { |
|
sprintf(xorriso->info_text, |
|
"... [@ = prompt suppression registered. Prompting disabled temporarily ] ...\n"); |
|
Xorriso_info(xorriso,0); |
|
} |
|
|
|
} else { |
|
Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */ |
|
sprintf(xorriso->info_text, |
|
"--- Unrecognized input beginning with @. Please enter someting else.\n"); |
|
Xorriso_info(xorriso,0); |
|
{ret= 3; goto ex;} |
|
} |
|
if(flag&2) |
|
{ret= 4; goto ex;} |
|
if(flag&1) |
|
{ret= 3; goto ex;} |
|
{ret= 1; goto ex;} |
|
} else if(flag&4) { |
|
|
|
if(strcmp(cpt,"i")==0 || strcmp(cpt,"I")==0 || |
|
strcmp(cpt,"n")==0 || strcmp(cpt,"N")==0 || |
|
*cpt==0) { |
|
{ret= 1; goto ex;} |
|
} else if(strcmp(cpt,"r")==0 || strcmp(cpt,"R")==0 || |
|
strcmp(cpt,"y")==0 || strcmp(cpt,"Y")==0) { |
|
{ret= 6; goto ex;} |
|
} else { |
|
/* >>> unknown input */ |
|
sprintf(xorriso->info_text, |
|
"--- Please enter one of : empty line, i,n, r,y, q,x, @, @@@\n"); |
|
Xorriso_info(xorriso,0); |
|
{ret= 3; goto ex;} |
|
} |
|
|
|
} else if(*cpt!=0 && !(flag&1)) { |
|
Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */ |
|
strcpy(xorriso->pending_option,cpt); |
|
xorriso->request_to_abort= 1; |
|
sprintf(xorriso->info_text, |
|
"-------------- [ Input of option registered. Operation ends ] ---------------\n"); |
|
Xorriso_info(xorriso,0); |
|
{ret= 2; goto ex;} |
|
|
|
} else if(*cpt!=0) { |
|
Xorriso_dialog_input(xorriso,cpt,strlen(line)+1,2); /* write to history */ |
|
sprintf(xorriso->info_text, |
|
"--- Please enter one of : empty line, @, @@@\n"); |
|
Xorriso_info(xorriso,0); |
|
{ret= 3; goto ex;} |
|
} |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(line); |
|
Xorriso_free_meM(previous_line); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= quoted multiline mode |
|
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, |
|
int *argc, char ***argv, int flag) |
|
{ |
|
char *line= NULL, *linept, *fgot; |
|
int l, base_length, append_line, ret, mem_linecount, i; |
|
|
|
Sfile_make_argv("", line, argc, argv, 2); |
|
if(flag & 2) |
|
{ret= 1; goto ex;} |
|
|
|
Xorriso_alloc_meM(line, char, 5 * SfileadrL + 2); |
|
|
|
mem_linecount= *linecount; |
|
linept= line; |
|
base_length= 0; |
|
while(1) { |
|
fgot= Sfile_fgets_n(linept, SfileadrL - base_length - 1, fp, |
|
!!(flag & (1 | 8))); |
|
if(fgot == NULL) { |
|
if(ferror(fp)) |
|
{ret= 0; goto ex;} |
|
if(linept != line) { |
|
sprintf(xorriso->info_text,"Open quotation mark at end of input"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
{ret= 2; goto ex;} |
|
} |
|
l= strlen(line); |
|
(*linecount)++; |
|
append_line= 0; |
|
if(flag & 1) { /* check whether the line is incomplete yet */ |
|
ret= Sfile_make_argv("", line, argc, argv, 16); |
|
if(ret < 0) |
|
goto ex; |
|
if(ret == 0 && !append_line) { |
|
line[l]= '\n'; |
|
line[l + 1]= 0; |
|
append_line= 1; |
|
} |
|
if(l > 0 && !append_line) |
|
if(line[l - 1] == '\\') { |
|
line[l - 1]= 0; |
|
append_line= 1; |
|
} |
|
} |
|
if(l >= SfileadrL) { |
|
sprintf(xorriso->info_text,"Input line too long !"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
if(!append_line) |
|
break; |
|
base_length= strlen(line); |
|
linept= line + base_length; |
|
} |
|
if((flag & 1) && !(flag & 8)) { |
|
ret= Sfile_make_argv("", line, argc, argv, |
|
1 | ((xorriso->bsl_interpretation & 3) << 5)); |
|
if(ret < 0) |
|
goto ex; |
|
if(flag & 4) |
|
for(i= 0; i < *argc; i++) { |
|
if((*argv)[i][0] == 0) { |
|
sprintf(xorriso->info_text, "Empty text as quoted argument in "); |
|
} else if(strlen((*argv)[i]) >= SfileadrL) { |
|
(*argv)[i][SfileadrL - 1]= 0; |
|
sprintf(xorriso->info_text, |
|
"Input text too long and now truncated in"); |
|
} else |
|
continue; |
|
if(mem_linecount + 1 < *linecount) |
|
sprintf(xorriso->info_text + strlen(xorriso->info_text), |
|
"lines %d to %d", mem_linecount + 1, *linecount); |
|
else |
|
sprintf(xorriso->info_text + strlen(xorriso->info_text), |
|
"line %d", mem_linecount + 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); |
|
} |
|
} else { |
|
(*argv)= Smem_malloC(sizeof(char *)); |
|
if(*argv == NULL) |
|
{ret= -1; goto ex;} |
|
(*argv)[0]= strdup(line); |
|
if((*argv)[0] == NULL) |
|
{ret= -1; goto ex;} |
|
*argc= 1; |
|
} |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(line); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_predict_linecount(struct XorrisO *xorriso, char *line, |
|
int *linecount, int flag) |
|
{ |
|
int width,l; |
|
char *spt,*ept; |
|
|
|
*linecount= 0; |
|
spt= line; |
|
width= xorriso->result_page_width; |
|
while(1) { |
|
ept= strchr(spt,'\n'); |
|
if(ept==NULL) |
|
l= strlen(spt); |
|
else |
|
l= ept-spt; |
|
l+= xorriso->result_open_line_len; |
|
if(ept!=NULL && l==0) |
|
(*linecount)++; |
|
else { |
|
(*linecount)+= l/width; |
|
if(ept==NULL) { |
|
xorriso->result_open_line_len= l%width; |
|
break; |
|
} |
|
(*linecount)+= !!(l%width); |
|
} |
|
xorriso->result_open_line_len= 0; |
|
spt= ept+1; |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_pager(struct XorrisO *xorriso, char *line, int flag) |
|
/* |
|
bit1= mark '@' by return 4 |
|
*/ |
|
/* return: <=0 error , 1=go on , 2=abort , 4=see flag bit1*/ |
|
{ |
|
int ret,linecount; |
|
char *info_text= NULL; |
|
|
|
if(xorriso->result_page_length<=0 || xorriso->request_not_to_ask || |
|
xorriso->dialog == 0) |
|
{ret= 1; goto ex;} |
|
Xorriso_predict_linecount(xorriso,line,&linecount,0); |
|
if(xorriso->result_line_counter+linecount>xorriso->result_page_length) { |
|
ask_for_page:; |
|
if(info_text == NULL) |
|
Xorriso_alloc_meM(info_text, char, 10*SfileadrL); |
|
strcpy(info_text,xorriso->info_text); |
|
sprintf(xorriso->info_text,"\n"); |
|
Xorriso_info(xorriso,0); |
|
sprintf(xorriso->info_text, |
|
".... [Press Enter to continue. @,Enter avoids further stops. @@@ aborts] ....\n"); |
|
Xorriso_info(xorriso,0); |
|
ret= Xorriso_request_confirmation(xorriso,flag&2); |
|
strcpy(xorriso->info_text,info_text); |
|
if(ret<=0) |
|
goto ex; |
|
if(ret==2) |
|
{ret= 2; goto ex;} |
|
if(ret==3) |
|
goto ask_for_page; |
|
} |
|
xorriso->result_line_counter+= linecount; |
|
ret= 1; |
|
ex:; |
|
Xorriso_free_meM(info_text); |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= no error message in case of failure |
|
*/ |
|
static int Xorriso_obtain_lock(struct XorrisO *xorriso, |
|
pthread_mutex_t *lock_handle, |
|
char *purpose, int flag) |
|
{ |
|
int ret; |
|
static int complaints= 0, complaint_limit= 5; |
|
|
|
ret= pthread_mutex_lock(lock_handle); |
|
if(ret != 0) { |
|
if(flag & 1) |
|
return(-1); |
|
/* Cannot report failure through the failing message output system */ |
|
complaints++; |
|
if(complaints <= complaint_limit) |
|
fprintf(stderr, |
|
"xorriso : pthread_mutex_lock() for %s returns %d\n", |
|
purpose, ret); |
|
return(-1); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= no error message in case of failure |
|
*/ |
|
static int Xorriso_release_lock(struct XorrisO *xorriso, |
|
pthread_mutex_t *lock_handle, |
|
char *purpose, int flag) |
|
{ |
|
int ret; |
|
static int complaints= 0, complaint_limit= 5; |
|
|
|
ret= pthread_mutex_unlock(lock_handle); |
|
if(ret != 0) { |
|
if(flag & 1) |
|
return(0); |
|
/* Cannot report failure through the failing message output system */ |
|
complaints++; |
|
if(complaints <= complaint_limit) |
|
fprintf(stderr, |
|
"xorriso : pthread_mutex_unlock() for %s returns %d\n", |
|
purpose, ret); |
|
return(0); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
static int Xorriso_lock_outlists(struct XorrisO *xorriso, int flag) |
|
{ |
|
int ret; |
|
|
|
ret= Xorriso_obtain_lock(xorriso, &(xorriso->result_msglists_lock), |
|
"outlists", 0); |
|
return(ret); |
|
} |
|
|
|
|
|
static int Xorriso_unlock_outlists(struct XorrisO *xorriso, int flag) |
|
{ |
|
int ret; |
|
|
|
ret= Xorriso_release_lock(xorriso, &(xorriso->result_msglists_lock), |
|
"outlists", 0); |
|
return(ret); |
|
} |
|
|
|
|
|
static int Xorriso_write_to_msglist(struct XorrisO *xorriso, |
|
struct Xorriso_lsT **xorriso_msglist, |
|
char *text, int flag) |
|
{ |
|
int ret, locked= 0; |
|
struct Xorriso_lsT *msglist; |
|
|
|
ret= Xorriso_lock_outlists(xorriso, 0); |
|
if(ret > 0) |
|
locked= 1; |
|
msglist= *xorriso_msglist; |
|
ret= Xorriso_lst_append_binary(&msglist, text, strlen(text) + 1, 0); |
|
if(ret <= 0) { |
|
ret= -1; goto ex; |
|
} |
|
if(*xorriso_msglist == NULL) |
|
*xorriso_msglist= msglist; |
|
ret= 1; |
|
ex:; |
|
if(locked) |
|
Xorriso_unlock_outlists(xorriso, 0); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_write_to_channel(struct XorrisO *xorriso, |
|
char *in_text, int channel_no, int flag) |
|
/* |
|
bit0= eventually backslash encode linefeeds |
|
bit1= text is the name of the log file for the given channel |
|
bit2= text is the name of the consolidated packet log file for all channels |
|
bit3= text is the name of the stderr redirection file |
|
bit15= with bit1 to bit3: close depicted log file |
|
*/ |
|
{ |
|
char *rpt, *npt, *text= NULL, *line= NULL; |
|
int ret= 1, info_redirected= 0, result_redirected= 0, l; |
|
char prefix[16]; |
|
FILE *logfile_fp, *pktlog_fp; |
|
static int num_channels= 4; |
|
static char channel_prefixes[4][4]= {".","R","I","M"}; |
|
int Xorriso_sieve_filter_msg(struct XorrisO *xorriso, char *msg, int flag); |
|
|
|
#ifdef Xorriso_fetch_with_msg_queueS |
|
static int complaints= 0, complaint_limit= 5; |
|
int locked= 0, uret; |
|
#endif |
|
|
|
text= in_text; /* might change due to backslash encoding */ |
|
|
|
if(channel_no<0 || channel_no>=num_channels) |
|
{ret= -1; goto ex;} |
|
|
|
#ifdef Xorriso_fetch_with_msg_queueS |
|
ret= pthread_mutex_lock(&(xorriso->write_to_channel_lock)); |
|
if(ret != 0) { |
|
/* Cannot report failure through the failing message output system */ |
|
complaints++; |
|
if(complaints <= complaint_limit) |
|
fprintf(stderr, |
|
"xorriso : pthread_mutex_lock() for write_to_channel returns %d\n", |
|
ret); |
|
/* Intentionally not aborting here */; |
|
} else |
|
locked= 1; |
|
#endif /* Xorriso_fetch_with_msg_queueS */ |
|
|
|
/* Logfiles */ |
|
logfile_fp= xorriso->logfile_fp[channel_no]; |
|
pktlog_fp= xorriso->pktlog_fp; |
|
if((flag&2) && logfile_fp!=NULL) { |
|
fprintf(logfile_fp, |
|
"! end ! end ! end ! end ! end ! end ! end ! end xorriso log : %s : %s\n", |
|
channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256)); |
|
fclose(logfile_fp); |
|
xorriso->logfile_fp[channel_no]= logfile_fp= NULL; |
|
} |
|
if((flag&4) && pktlog_fp!=NULL) { |
|
fprintf(pktlog_fp, |
|
"I:1:! end ! end ! end ! end ! end ! end ! end ! end xorriso log : %s : %s\n", |
|
channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256)); |
|
fclose(pktlog_fp); |
|
xorriso->pktlog_fp= pktlog_fp= NULL; |
|
} |
|
if((flag & 8) && xorriso->stderr_fp != NULL) { |
|
fclose(xorriso->stderr_fp); |
|
xorriso->stderr_fp= NULL; |
|
} |
|
if(flag&(1<<15)) |
|
{ret= 1; goto ex;} |
|
if((flag&2)) { |
|
xorriso->logfile_fp[channel_no]= logfile_fp= fopen(text,"a"); |
|
if(logfile_fp==NULL) |
|
{ret= 0; goto ex;} |
|
fprintf(logfile_fp, |
|
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xorriso log : %s : %s\n", |
|
channel_prefixes[channel_no],Sfile_datestr(time(0),1|2|256)); |
|
fflush(logfile_fp); |
|
} |
|
if((flag&4)) { |
|
xorriso->pktlog_fp= pktlog_fp= fopen(text,"a"); |
|
if(pktlog_fp==NULL) |
|
{ret= 0; goto ex;} |
|
fprintf(pktlog_fp, |
|
"I:1:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! xorriso log : . : %s\n", |
|
Sfile_datestr(time(0),1|2|256)); |
|
fflush(pktlog_fp); |
|
} |
|
if(flag & 8) { |
|
ret= truncate(text, (off_t) 0); |
|
if(ret == -1 && errno != ENOENT) |
|
{ret= 0; goto ex;} |
|
xorriso->stderr_fp= fopen(text, "a"); |
|
if(xorriso->stderr_fp == NULL) |
|
{ret= 0; goto ex;} |
|
} |
|
if(flag & (2 | 4 | 8)) |
|
{ret= 1; goto ex;} |
|
|
|
/* Eventually perform backslash encoding of non-printable characters */ |
|
if(((xorriso->bsl_interpretation & 32) && channel_no == 1) || |
|
((xorriso->bsl_interpretation & 64) && channel_no == 2)) { |
|
ret= Sfile_bsl_encoder(&text, text, strlen(text), 1 | 2 | 4); |
|
if(ret <= 0) |
|
{ret= -1; goto ex;} |
|
} |
|
|
|
/* Pick interesting words for the Xorriso_sieve API */ |
|
Xorriso_sieve_filter_msg(xorriso, text, |
|
(channel_no > 0 ? channel_no - 1 : 0)); |
|
|
|
/* Eventually perform message redirection */ |
|
if(xorriso->msglist_stackfill > 0) { |
|
if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 1) |
|
result_redirected= 1; |
|
if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 2) |
|
info_redirected= 1; |
|
} |
|
|
|
/* Non-redirected output */ |
|
if(!xorriso->packet_output) { |
|
if(channel_no==1 || channel_no==3) { |
|
if(result_redirected) { |
|
ret= Xorriso_write_to_msglist(xorriso, |
|
&(xorriso->result_msglists[xorriso->msglist_stackfill - 1]), |
|
text, 0); |
|
if(ret <= 0) |
|
{ ret= -1; goto ex; } |
|
} else { |
|
printf("%s",text); |
|
fflush(stdout); |
|
} |
|
} |
|
if(channel_no==2 || channel_no==3) { |
|
if(info_redirected) { |
|
ret= Xorriso_write_to_msglist(xorriso, |
|
&(xorriso->info_msglists[xorriso->msglist_stackfill - 1]), |
|
text, 0); |
|
if(ret <= 0) |
|
{ ret= -1; goto ex; } |
|
} else { |
|
if(xorriso->stderr_fp != NULL) { |
|
fprintf(xorriso->stderr_fp, "%s", text); |
|
fflush(xorriso->stderr_fp); |
|
} else |
|
fprintf(stderr, "%s", text); |
|
} |
|
} |
|
if(logfile_fp!=NULL) { |
|
fprintf(logfile_fp,"%s",text); |
|
fflush(logfile_fp); |
|
} |
|
if(pktlog_fp==NULL) |
|
{ret= 1; goto ex;} |
|
} |
|
rpt= text; |
|
sprintf(prefix,"%s:x: ",channel_prefixes[channel_no]); |
|
while(*rpt!=0) { |
|
npt= strchr(rpt,'\n'); |
|
if(npt==NULL) |
|
prefix[2]= '0'; |
|
else |
|
prefix[2]= '1'; |
|
if(!result_redirected) { |
|
if(xorriso->packet_output) { |
|
ret= fwrite(prefix,5,1,stdout); |
|
if(ret<=0) |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
if(pktlog_fp!=NULL) { |
|
ret= fwrite(prefix,5,1,pktlog_fp); |
|
if(ret<=0) |
|
{ret= 0; goto ex;} |
|
} |
|
if(npt==NULL) { |
|
if(xorriso->packet_output) { |
|
if(result_redirected) { |
|
l= strlen(rpt); |
|
Xorriso_alloc_meM(line, char, 5 + l + 1 + 1); |
|
memcpy(line, prefix, 5); |
|
memcpy(line + 5, rpt, l); |
|
line[5 + l] = '\n'; |
|
line[5 + l + 1] = 0; |
|
ret= Xorriso_write_to_msglist(xorriso, |
|
&(xorriso->result_msglists[xorriso->msglist_stackfill - 1]), |
|
line, 0); |
|
Xorriso_free_meM(line); |
|
line= NULL; |
|
if(ret <= 0) |
|
{ ret= -1; goto ex; } |
|
} else { |
|
ret= fwrite(rpt,strlen(rpt),1,stdout); |
|
if(ret<=0) |
|
{ret= 0; goto ex;} |
|
ret= fwrite("\n",1,1,stdout); |
|
if(ret<=0) |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
if(pktlog_fp!=NULL) { |
|
ret= fwrite(rpt,strlen(rpt),1,pktlog_fp); |
|
if(ret<=0) |
|
{ret= 0; goto ex;} |
|
ret= fwrite("\n",1,1,pktlog_fp); |
|
if(ret<=0) |
|
{ret= 0; goto ex;} |
|
} |
|
break; |
|
} else { |
|
if(xorriso->packet_output) { |
|
if(result_redirected) { |
|
l= npt + 1 - rpt; |
|
Xorriso_alloc_meM(line, char, 5 + l + 1); |
|
memcpy(line, prefix, 5); |
|
memcpy(line + 5, rpt, l); |
|
line[5 + l] = 0; |
|
ret= Xorriso_write_to_msglist(xorriso, |
|
&(xorriso->result_msglists[xorriso->msglist_stackfill - 1]), |
|
line, 0); |
|
Xorriso_free_meM(line); |
|
line= NULL; |
|
if(ret <= 0) |
|
{ ret= -1; goto ex; } |
|
} else { |
|
ret= fwrite(rpt,npt+1-rpt,1,stdout); |
|
if(ret<=0) |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
if(pktlog_fp!=NULL) { |
|
ret= fwrite(rpt,npt+1-rpt,1,pktlog_fp); |
|
if(ret<=0) |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
rpt= npt+1; |
|
} |
|
if(xorriso->packet_output) |
|
fflush(stdout); |
|
if(pktlog_fp!=NULL) |
|
fflush(pktlog_fp); |
|
ret= 1; |
|
ex: |
|
if(text != in_text && text != NULL) |
|
free(text); |
|
Xorriso_free_meM(line); |
|
|
|
#ifdef Xorriso_fetch_with_msg_queueS |
|
|
|
if(locked) { |
|
uret= pthread_mutex_unlock(&(xorriso->write_to_channel_lock)); |
|
if(uret != 0) { |
|
/* Cannot report failure through the failing message output system */ |
|
complaints++; |
|
if(complaints <= complaint_limit) |
|
fprintf(stderr, |
|
"xorriso : pthread_mutex_unlock() for write_to_channel returns %d\n", |
|
uret); |
|
} |
|
} |
|
|
|
#endif /* Xorriso_fetch_with_msg_queueS */ |
|
|
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle, |
|
int flag) |
|
{ |
|
int ret, locked= 0; |
|
|
|
ret= Xorriso_lock_outlists(xorriso, 0); |
|
if(ret > 0) |
|
locked= 1; |
|
if(xorriso->msglist_stackfill + 1 >= Xorriso_max_outlist_stacK) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Overflow of message output redirection stack", 0, "FATAL", 0); |
|
ret= -1; goto ex; |
|
} |
|
if((flag & 3) == 0) |
|
flag|= 3; |
|
xorriso->msglist_stackfill++; |
|
xorriso->result_msglists[xorriso->msglist_stackfill - 1]= NULL; |
|
xorriso->info_msglists[xorriso->msglist_stackfill - 1]= NULL; |
|
xorriso->msglist_flags[xorriso->msglist_stackfill - 1]= flag & 3; |
|
*stack_handle= xorriso->msglist_stackfill - 1; |
|
ret= 1; |
|
ex:; |
|
if(locked) |
|
Xorriso_unlock_outlists(xorriso, 0); |
|
return(ret); |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_fetch_outlists(struct XorrisO *xorriso, int stack_handle, |
|
struct Xorriso_lsT **result_list, |
|
struct Xorriso_lsT **info_list, int flag) |
|
{ |
|
int ret, locked= 0; |
|
|
|
#ifdef Xorriso_fetch_with_msg_queueS |
|
|
|
ret= Xorriso_process_msg_queues(xorriso, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
#endif /* Xorriso_fetch_with_msg_queueS */ |
|
|
|
if((flag & 3) == 0) |
|
flag|= 3; |
|
|
|
ret= Xorriso_lock_outlists(xorriso, 0); |
|
if(ret > 0) |
|
locked= 1; |
|
|
|
if(stack_handle == -1) |
|
stack_handle= xorriso->msglist_stackfill - 1; |
|
if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Program error: Wrong message output redirection stack handle", |
|
0, "FATAL", 0); |
|
ret= -1; goto ex; |
|
} |
|
|
|
if(flag & 1) { |
|
*result_list= xorriso->result_msglists[stack_handle]; |
|
xorriso->result_msglists[stack_handle]= NULL; |
|
} |
|
if(flag & 2) { |
|
*info_list= xorriso->info_msglists[stack_handle]; |
|
xorriso->info_msglists[stack_handle]= NULL; |
|
} |
|
|
|
ret= 1; |
|
ex:; |
|
if(locked) |
|
Xorriso_unlock_outlists(xorriso, 0); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_peek_outlists(struct XorrisO *xorriso, int stack_handle, |
|
int timeout, int flag) |
|
{ |
|
int ret, locked= 0, yes= 0; |
|
static int u_wait= 19000; |
|
time_t start_time; |
|
|
|
if((flag & 3) == 0) |
|
flag|= 3; |
|
if(stack_handle == -1) |
|
stack_handle= xorriso->msglist_stackfill - 1; |
|
start_time= time(NULL); |
|
|
|
try_again:; |
|
ret= Xorriso_obtain_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 0); |
|
if(ret <= 0) |
|
{yes= -2; goto ex;} |
|
locked= 1; |
|
|
|
yes= 0; |
|
if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) |
|
{yes= -1; goto ex;} |
|
if(flag & 1) |
|
yes|= (xorriso->result_msglists[stack_handle] != NULL); |
|
if(flag & 2) |
|
yes|= (xorriso->info_msglists[stack_handle] != NULL); |
|
if(xorriso->msg_watcher_state == 2 && xorriso->msgw_msg_pending) |
|
yes|= 2; |
|
|
|
ret= Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 0); |
|
if(ret <= 0) |
|
{yes= -2; goto ex;} |
|
locked= 0; |
|
|
|
if(yes && (flag & 4)) { |
|
usleep(u_wait); |
|
if(time(NULL) <= start_time + timeout) |
|
goto try_again; |
|
} |
|
|
|
ex:; |
|
if(locked) { |
|
ret= Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 0); |
|
if(ret <= 0 && yes >= 0) |
|
yes= -2; |
|
} |
|
return(yes); |
|
} |
|
|
|
|
|
int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle, |
|
struct Xorriso_lsT **result_list, |
|
struct Xorriso_lsT **info_list, int flag) |
|
{ |
|
int i, ret, locked= 0; |
|
|
|
ret= Xorriso_lock_outlists(xorriso, 0); |
|
if(ret > 0) |
|
locked= 1; |
|
|
|
if(stack_handle == -1) |
|
stack_handle= xorriso->msglist_stackfill - 1; |
|
if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Program error: Wrong message output redirection stack handle", |
|
0, "FATAL", 0); |
|
ret= -1; goto ex; |
|
} |
|
|
|
/* Concatenate all redirections above stack_handle */ |
|
*result_list= NULL; |
|
*info_list= NULL; |
|
for(i = stack_handle; i < xorriso->msglist_stackfill; i++) { |
|
if(*result_list == NULL) |
|
*result_list= xorriso->result_msglists[i]; |
|
else |
|
Xorriso_lst_concat(*result_list, xorriso->result_msglists[i], 0); |
|
if(*info_list == NULL) |
|
*info_list= xorriso->info_msglists[i]; |
|
else |
|
Xorriso_lst_concat(*info_list, xorriso->info_msglists[i], 0); |
|
} |
|
xorriso->msglist_stackfill= stack_handle; |
|
|
|
ret= 1; |
|
ex:; |
|
if(locked) |
|
Xorriso_unlock_outlists(xorriso, 0); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_info_handler_stderr(void *handle, char *text) |
|
{ |
|
struct XorrisO *xorriso; |
|
|
|
xorriso= (struct XorrisO *) handle; |
|
if(xorriso->stderr_fp != NULL) { |
|
fprintf(xorriso->stderr_fp, "%s", text); |
|
fflush(xorriso->stderr_fp); |
|
} else { |
|
fprintf(stderr, "%s", text); |
|
fflush(stderr); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_result_handler_stdout(void *handle, char *text) |
|
{ |
|
printf("%s", text); |
|
fflush(stdout); |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_result_handler_pkt(void *handle, char *text) |
|
{ |
|
int nl= -1, ret, l; |
|
struct XorrisO *xorriso; |
|
|
|
xorriso= (struct XorrisO *) handle; |
|
|
|
if(!xorriso->packet_output) |
|
return Xorriso_result_handler_stdout(handle, text); |
|
|
|
/* Interpret pkt_output */ |
|
l= strlen(text); |
|
if(l >= 5) { |
|
if(strchr("RIM", text[0]) != NULL && text[1] == ':' && |
|
strchr("01", text[2]) != NULL && text[3] == ':' && text[4] == ' ') |
|
nl= (text[2] == '1'); |
|
} |
|
if(nl < 0) /* Not pkt_output format */ |
|
return Xorriso_result_handler_stdout(handle, text); |
|
|
|
if(nl == 0) { |
|
/* Suppress newline */ |
|
if(text[l - 1] == '\n') |
|
l--; |
|
} |
|
|
|
if(text[0] == 'R') { |
|
ret= fwrite(text + 5, l - 5, 1, stdout); |
|
} else { |
|
ret= fwrite(text + 5, l - 5, 1, |
|
xorriso->stderr_fp != NULL ? xorriso->stderr_fp : stderr); |
|
} |
|
if(ret <= 0) |
|
return(0); |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_process_msg_lists(struct XorrisO *xorriso, |
|
struct Xorriso_lsT *result_list, |
|
struct Xorriso_lsT *info_list, |
|
int *line_count, int flag) |
|
{ |
|
struct Xorriso_lsT *lpt; |
|
int ret; |
|
int (*handler)(void *handle, char *text); |
|
void *handle; |
|
|
|
handler= xorriso->msgw_result_handler; |
|
handle= xorriso->msgw_result_handle; |
|
if(handler == NULL) { |
|
handler= Xorriso_result_handler_pkt; |
|
handle= xorriso; |
|
} |
|
for(lpt= result_list; lpt != NULL; lpt= lpt->next) { |
|
(*line_count)++; |
|
ret= (*handler)(handle, Xorriso_lst_get_text(lpt, 0)); |
|
if(ret < 0) |
|
return(-1); |
|
} |
|
handler= xorriso->msgw_info_handler; |
|
handle= xorriso->msgw_info_handle; |
|
if(handler == NULL) { |
|
handler= Xorriso_info_handler_stderr; |
|
handle= xorriso; |
|
} |
|
for(lpt= info_list; lpt != NULL; lpt= lpt->next) { |
|
(*line_count)++; |
|
ret= (*handler)(handle, Xorriso_lst_get_text(lpt, 0)); |
|
if(ret < 0) |
|
return(-1); |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
static void *Xorriso_msg_watcher(void *state_pt) |
|
{ |
|
struct XorrisO *xorriso; |
|
int ret, u_wait= 25000, line_count, sleep_thresh= 20; |
|
struct Xorriso_lsT *result_list= NULL, *info_list= NULL; |
|
static int debug_sev= 0; |
|
|
|
xorriso= (struct XorrisO *) state_pt; |
|
|
|
if(debug_sev == 0) |
|
Xorriso__text_to_sev("DEBUG", &debug_sev, 0); |
|
|
|
xorriso->msg_watcher_state= 2; |
|
if(xorriso->msgw_info_handler != NULL && |
|
debug_sev < xorriso->report_about_severity && |
|
debug_sev < xorriso->abort_on_severity) |
|
(*xorriso->msgw_info_handler)(xorriso, |
|
"xorriso : DEBUG : Concurrent message watcher started\n"); |
|
while(1) { |
|
line_count= 0; |
|
|
|
/* Watch out for end request in xorriso */ |
|
if(xorriso->msg_watcher_state == 3) |
|
break; |
|
|
|
Xorriso_obtain_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 1); |
|
xorriso->msgw_msg_pending= 1; |
|
ret= Xorriso_fetch_outlists(xorriso, -1, &result_list, &info_list, 3); |
|
if(ret > 0) { |
|
/* Process fetched lines */ |
|
xorriso->msgw_msg_pending= 2; |
|
Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 1); |
|
ret= Xorriso_process_msg_lists(xorriso, result_list, info_list, |
|
&line_count, 0); |
|
xorriso->msgw_msg_pending= 0; |
|
Xorriso_lst_destroy_all(&result_list, 0); |
|
Xorriso_lst_destroy_all(&info_list, 0); |
|
if(ret < 0) |
|
break; |
|
} else { |
|
xorriso->msgw_msg_pending= 0; |
|
Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 1); |
|
} |
|
xorriso->msgw_msg_pending= 0; |
|
|
|
if(ret < 0) |
|
break; |
|
|
|
if(line_count < sleep_thresh) |
|
usleep(u_wait); |
|
} |
|
if(xorriso->msgw_info_handler != NULL && |
|
debug_sev < xorriso->report_about_severity && |
|
debug_sev < xorriso->abort_on_severity) |
|
(*xorriso->msgw_info_handler)(xorriso, |
|
"xorriso : DEBUG : Concurrent message watcher ended\n"); |
|
xorriso->msg_watcher_state= 0; |
|
return(NULL); |
|
} |
|
|
|
|
|
int Xorriso_start_msg_watcher(struct XorrisO *xorriso, |
|
int (*result_handler)(void *handle, char *text), |
|
void *result_handle, |
|
int (*info_handler)(void *handle, char *text), |
|
void *info_handle, |
|
int flag) |
|
{ |
|
int ret, u_wait= 1000, locked= 0, pushed= 0, uret, line_count= 0; |
|
struct Xorriso_lsT *result_list= NULL, *info_list= NULL; |
|
pthread_attr_t attr; |
|
pthread_attr_t *attr_pt = NULL; |
|
pthread_t thread; |
|
|
|
ret= pthread_mutex_lock(&(xorriso->msg_watcher_lock)); |
|
if(ret != 0) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Cannot aquire mutex lock for managing concurrent message watcher", |
|
ret, "FATAL", 0); |
|
ret= -1; goto ex; |
|
} |
|
locked= 1; |
|
|
|
/* Check for running watcher */ |
|
if(xorriso->msg_watcher_state > 0) { |
|
sprintf(xorriso->info_text, |
|
"There is already a concurrent message watcher running"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
|
|
ret= Xorriso_push_outlists(xorriso, &(xorriso->msgw_stack_handle), 3); |
|
if(ret <= 0) |
|
goto ex; |
|
pushed= 1; |
|
|
|
/* Register watcher */ |
|
xorriso->msgw_result_handler= result_handler; |
|
xorriso->msgw_result_handle= result_handle; |
|
xorriso->msgw_info_handler= info_handler; |
|
xorriso->msgw_info_handle= info_handle; |
|
xorriso->msg_watcher_state= 1; |
|
|
|
/* Start thread */ |
|
pthread_attr_init(&attr); |
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
|
attr_pt= &attr; |
|
ret= pthread_create(&thread, attr_pt, Xorriso_msg_watcher, xorriso); |
|
if(ret != 0) { |
|
sprintf(xorriso->info_text, |
|
"Cannot create thread for concurrent message watcher"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
|
|
/* Wait until watcher has indicated start */ |
|
while(xorriso->msg_watcher_state == 1) { |
|
|
|
/* >>> have a timeout ? */; |
|
|
|
usleep(u_wait); |
|
} |
|
|
|
ret= 1; |
|
ex:; |
|
if(ret <= 0 && pushed) { |
|
uret= Xorriso_pull_outlists(xorriso, xorriso->msgw_stack_handle, |
|
&result_list, &info_list, 0); |
|
if(uret > 0) { |
|
xorriso->msgw_result_handler= NULL; |
|
xorriso->msgw_info_handler= NULL; |
|
Xorriso_process_msg_lists(xorriso, result_list, info_list, |
|
&line_count, 0); |
|
Xorriso_lst_destroy_all(&result_list, 0); |
|
Xorriso_lst_destroy_all(&info_list, 0); |
|
} |
|
} |
|
if(locked) { |
|
uret= pthread_mutex_unlock(&(xorriso->msg_watcher_lock)); |
|
if(uret != 0) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Cannot release mutex lock for managing concurrent message watcher", |
|
uret, "FATAL", 0); |
|
ret= -1; |
|
} |
|
} |
|
return(ret); |
|
} |
|
|
|
|
|
/* @param flag bit0= do not complain loudly if no wather is active |
|
*/ |
|
int Xorriso_stop_msg_watcher(struct XorrisO *xorriso, int flag) |
|
{ |
|
int ret, u_wait= 1000, locked= 0, uret, line_count= 0; |
|
struct Xorriso_lsT *result_list= NULL, *info_list= NULL; |
|
|
|
if((flag & 1) && xorriso->msg_watcher_state != 2) |
|
/* Roughly tolerate non-running watcher */ |
|
{ret= 0; goto ex;} |
|
|
|
ret= pthread_mutex_lock(&(xorriso->msg_watcher_lock)); |
|
if(ret != 0) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Cannot aquire mutex lock for managing concurrent message watcher", |
|
ret, "FATAL", 0); |
|
ret= -1; goto ex; |
|
} |
|
locked= 1; |
|
|
|
/* Check for running watcher */ |
|
if(xorriso->msg_watcher_state != 2) { |
|
sprintf(xorriso->info_text, |
|
"There is no concurrent message watcher running"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "SORRY", 0); |
|
ret= 0; goto ex; |
|
} |
|
|
|
/* Inform watcher of desire to stop it */ |
|
xorriso->msg_watcher_state= 3; |
|
|
|
/* Wait until watcher has indicated its end */ |
|
while(xorriso->msg_watcher_state != 0) { |
|
|
|
/* >>> have a timeout ? */; |
|
|
|
usleep(u_wait); |
|
} |
|
|
|
Xorriso_obtain_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 1); |
|
xorriso->msgw_msg_pending= 1; |
|
ret= Xorriso_pull_outlists(xorriso, xorriso->msgw_stack_handle, |
|
&result_list, &info_list, 0); |
|
if(ret > 0) { |
|
xorriso->msgw_msg_pending= 2; |
|
Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 1); |
|
Xorriso_process_msg_lists(xorriso, result_list, info_list, |
|
&line_count, 0); |
|
xorriso->msgw_msg_pending= 0; |
|
Xorriso_lst_destroy_all(&result_list, 0); |
|
Xorriso_lst_destroy_all(&info_list, 0); |
|
} else { |
|
xorriso->msgw_msg_pending= 0; |
|
Xorriso_release_lock(xorriso, &(xorriso->msgw_fetch_lock), |
|
"message watcher fetch operation", 1); |
|
} |
|
|
|
xorriso->msgw_result_handler= NULL; |
|
xorriso->msgw_info_handler= NULL; |
|
|
|
ret= 1; |
|
ex:; |
|
if(locked) { |
|
uret= pthread_mutex_unlock(&(xorriso->msg_watcher_lock)); |
|
if(uret != 0) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"Cannot release mutex lock for managing concurrent message watcher", |
|
uret, "FATAL", 0); |
|
ret= -1; |
|
} |
|
} |
|
return(ret); |
|
} |
|
|
|
|
|
/* -------------------------- Xorriso_msg_sievE -------------------------- */ |
|
|
|
struct Xorriso_msg_filteR { |
|
char *name; |
|
char *prefix; |
|
char *separators; |
|
int channels; /* What to watch: bit0=result , bit1=info , bit2=mark */ |
|
|
|
int num_words; |
|
int *word_idx; |
|
int last_word_line_end; |
|
|
|
/* Oldest result gets discarded when new surpassed threshold */ |
|
int max_results; |
|
|
|
struct Xorriso_lsT *results; /* Serialized tuples of num_words */ |
|
int num_results; |
|
int num_delivered; |
|
struct Xorriso_lsT *next_to_deliver; |
|
|
|
struct Xorriso_msg_filteR *prev; |
|
struct Xorriso_msg_filteR *next; |
|
}; |
|
int Xorriso_msg_filter_destroy(struct Xorriso_msg_filteR **o, int flag); |
|
|
|
|
|
int Xorriso_msg_filter_new(struct Xorriso_msg_filteR **o, char *name, |
|
struct Xorriso_msg_filteR *prev, |
|
struct Xorriso_msg_filteR *next, |
|
int flag) |
|
{ |
|
struct Xorriso_msg_filteR *m; |
|
|
|
m= (*o)= TSOB_FELD(struct Xorriso_msg_filteR, 1); |
|
if((*o) == NULL) |
|
return(-1); |
|
m->name= NULL; |
|
m->prefix= NULL; |
|
m->separators= NULL; |
|
m->channels= 7; |
|
m->num_words= 0; |
|
m->word_idx= NULL; |
|
m->last_word_line_end= flag & 1; |
|
m->max_results= 1; |
|
m->results= NULL; |
|
m->num_results= 0; |
|
m->num_delivered= 0; |
|
m->next_to_deliver= NULL; |
|
|
|
m->name= strdup(name); |
|
if(m->name == NULL) |
|
goto failure; |
|
|
|
m->prev= prev; |
|
if(prev != NULL) |
|
prev->next= m; |
|
m->next= next; |
|
if(next != NULL) |
|
next->prev= m; |
|
return(1); |
|
failure: |
|
Xorriso_msg_filter_destroy(o, 0); |
|
return(-1); |
|
} |
|
|
|
|
|
int Xorriso_msg_filter_destroy(struct Xorriso_msg_filteR **o, int flag) |
|
{ |
|
struct Xorriso_msg_filteR *m; |
|
|
|
if((*o)==NULL) |
|
return(0); |
|
m= *o; |
|
if(m->name != NULL) |
|
free(m->name); |
|
if(m->prefix != NULL) |
|
free(m->prefix); |
|
if(m->separators != NULL) |
|
free(m->separators); |
|
if(m->word_idx != NULL) |
|
free((char *) m->word_idx); |
|
if(m->results != NULL) |
|
Xorriso_lst_destroy_all(&(m->results), 0); |
|
if(m->prev != NULL) |
|
m->prev->next= m->next; |
|
if(m->next != NULL) |
|
m->next->prev= m->prev; |
|
|
|
free(*o); |
|
*o= NULL; |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_msg_filter_set_words(struct Xorriso_msg_filteR *m, |
|
int num_words, int *word_idx, int flag) |
|
{ |
|
int i; |
|
|
|
if(m->word_idx != NULL) |
|
free(m->word_idx); |
|
m->num_words= 0; |
|
if(num_words <= 0) |
|
return(1); |
|
m->word_idx= TSOB_FELD(int, num_words); |
|
if(m->word_idx == NULL) |
|
return(-1); |
|
for(i= 0; i < num_words; i++) |
|
m->word_idx[i]= word_idx[i]; |
|
m->num_words= num_words; |
|
return(1); |
|
} |
|
|
|
|
|
struct Xorriso_msg_sievE { |
|
|
|
int num_filters; |
|
|
|
struct Xorriso_msg_filteR *first_filter; |
|
|
|
}; |
|
|
|
|
|
int Xorriso_msg_sieve_new(struct Xorriso_msg_sievE **o, int flag) |
|
{ |
|
struct Xorriso_msg_sievE *m; |
|
|
|
m= (*o)= TSOB_FELD(struct Xorriso_msg_sievE, 1); |
|
if((*o) == NULL) |
|
return(-1); |
|
m->num_filters= 0; |
|
m->first_filter= NULL; |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_msg_sieve_destroy(struct Xorriso_msg_sievE **o, int flag) |
|
{ |
|
struct Xorriso_msg_sievE *m; |
|
struct Xorriso_msg_filteR *f, *next_f= NULL; |
|
|
|
if((*o) == NULL) |
|
return(0); |
|
m= *o; |
|
for(f= m->first_filter; f != NULL; f= next_f) { |
|
next_f= f->next; |
|
Xorriso_msg_filter_destroy(&f, 0); |
|
} |
|
free(*o); |
|
*o= NULL; |
|
return(1); |
|
} |
|
|
|
|
|
/* API */ |
|
int Xorriso_sieve_add_filter(struct XorrisO *xorriso, char *name, |
|
int channels, char *prefix, char *separators, |
|
int num_words, int *word_idx, int max_results, |
|
int flag) |
|
{ |
|
int ret; |
|
struct Xorriso_msg_sievE *sieve= NULL; |
|
struct Xorriso_msg_filteR *filter; |
|
|
|
if(xorriso->msg_sieve == NULL) { |
|
ret= Xorriso_msg_sieve_new(&sieve, 0); |
|
if(ret <= 0) |
|
goto no_mem; |
|
xorriso->msg_sieve= sieve; |
|
} else |
|
sieve= xorriso->msg_sieve; |
|
ret= Xorriso_msg_filter_new(&filter, name, NULL, sieve->first_filter, |
|
flag & 1); |
|
if(ret <= 0) |
|
goto no_mem; |
|
sieve->first_filter= filter; |
|
ret= Xorriso_msg_filter_set_words(filter, num_words, word_idx, 0); |
|
if(ret <= 0) |
|
goto no_mem; |
|
if(prefix != NULL) |
|
filter->prefix= strdup(prefix); |
|
if(separators != NULL) |
|
filter->separators= strdup(separators); |
|
filter->channels= channels; |
|
filter->max_results= max_results; |
|
(sieve->num_filters)++; |
|
return(1); |
|
|
|
no_mem:; |
|
Xorriso_msg_sieve_destroy(&sieve, 0); |
|
Xorriso_no_malloc_memory(xorriso, NULL, 0); |
|
return(-1); |
|
} |
|
|
|
|
|
/* API */ |
|
int Xorriso_sieve_dispose(struct XorrisO *xorriso, int flag) |
|
{ |
|
Xorriso_msg_sieve_destroy(&(xorriso->msg_sieve), 0); |
|
return(1); |
|
} |
|
|
|
|
|
/* API */ |
|
int Xorriso_sieve_clear_results(struct XorrisO *xorriso, int flag) |
|
{ |
|
struct Xorriso_msg_filteR *f; |
|
|
|
if(xorriso->msg_sieve == NULL) |
|
return(1); |
|
for(f= xorriso->msg_sieve->first_filter; f != NULL; f= f->next) { |
|
f->num_results= 0; |
|
f->num_delivered= 0; |
|
if(f->results != NULL) |
|
Xorriso_lst_destroy_all(&(f->results), 0); |
|
f->next_to_deliver= NULL; |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
/* API */ |
|
/* @param flag bit0= Reset reading to first matching result |
|
bit1= Only inquire number of available results. |
|
Do not allocate memory. |
|
bit2= If *argv is not NULL, then free it before attaching |
|
new memory. |
|
bit3= Do not read recorded data but rather list all filter names |
|
*/ |
|
int Xorriso_sieve_get_result(struct XorrisO *xorriso, char *name, |
|
int *argc, char ***argv, int *available, int flag) |
|
{ |
|
struct Xorriso_msg_filteR *f; |
|
struct Xorriso_lsT *lst; |
|
int i; |
|
|
|
if(flag & 4) |
|
Xorriso__dispose_words(argc, argv); |
|
*argc= 0; |
|
*argv= NULL; |
|
|
|
if(xorriso->msg_sieve == NULL) |
|
return(0); |
|
|
|
if(flag & 8) { |
|
if(xorriso->msg_sieve->num_filters <= 0) |
|
return(0); |
|
*argv= calloc(xorriso->msg_sieve->num_filters, sizeof(char *)); |
|
if(*argv == NULL) |
|
goto no_mem; |
|
*argc= xorriso->msg_sieve->num_filters; |
|
for(i= 0; i < *argc; i++) |
|
(*argv)[i]= NULL; |
|
i= 0; |
|
for(f= xorriso->msg_sieve->first_filter; f != NULL; f= f->next) { |
|
(*argv)[*argc - i - 1]= strdup(f->name); |
|
if((*argv)[*argc - i - 1] == NULL) |
|
goto no_mem; |
|
i++; |
|
} |
|
*argc= i; |
|
return(1); |
|
} |
|
|
|
for(f= xorriso->msg_sieve->first_filter; f != NULL; f= f->next) { |
|
if(strcmp(f->name, name) != 0) |
|
continue; |
|
*available= f->num_results - f->num_delivered; |
|
if(*available <= 0) |
|
return(0); |
|
if(flag & 2) |
|
return(1); |
|
|
|
if(flag & 1) { |
|
f->num_delivered= 0; |
|
f->next_to_deliver= NULL; |
|
} |
|
if(f->next_to_deliver == NULL) { |
|
f->next_to_deliver= f->results; |
|
for(i= 0; i < f->num_words * f->num_delivered; i++) |
|
if(f->next_to_deliver != NULL) |
|
f->next_to_deliver= Xorriso_lst_get_next(f->next_to_deliver, 0); |
|
} |
|
if(f->next_to_deliver == NULL) { |
|
/* Should not happen */ |
|
*available= 0; |
|
break; |
|
} |
|
if(f->num_words <= 0) |
|
return(1); |
|
|
|
*argv= calloc(f->num_words, sizeof(char *)); |
|
if(*argv == NULL) |
|
goto no_mem; |
|
*argc= f->num_words; |
|
for(i= 0; i < *argc; i++) |
|
(*argv)[i]= NULL; |
|
|
|
lst= f->next_to_deliver; |
|
for(i= 0; i < *argc; i++) { |
|
if(lst != NULL) { |
|
(*argv)[i]= strdup(Xorriso_lst_get_text(lst, 0)); |
|
if((*argv)[i] == NULL) |
|
goto no_mem; |
|
} else { |
|
|
|
/* >>> ??? should not happen */; |
|
|
|
} |
|
lst= Xorriso_lst_get_next(lst, 0); |
|
} |
|
f->next_to_deliver= lst; |
|
(f->num_delivered)++; |
|
(*available)--; |
|
return(1); |
|
} |
|
return(-2); |
|
no_mem: |
|
if(*argv != NULL) |
|
Xorriso__dispose_words(argc, argv); |
|
Xorriso_no_malloc_memory(xorriso, NULL, 0); |
|
return(-1); |
|
} |
|
|
|
|
|
int Xorriso_sieve_big(struct XorrisO *xorriso, int flag) |
|
{ |
|
struct Xorriso_sieve_big_filteR { |
|
char *name; |
|
int channels; |
|
char *prefix; |
|
char *separators; |
|
int num_words; |
|
int word_idx[6]; |
|
int max_results; |
|
int flag; |
|
}; |
|
static struct Xorriso_sieve_big_filteR filters[] = { |
|
{"-changes_pending", 3, "-changes_pending", "", 1, |
|
{ 0, -1, -1, -1, -1, -1}, 1, 0}, |
|
{"? -dev", 3, "? -dev", "", 4, { 0, 1, 3, 4, -1, -1}, |
|
10, 0}, |
|
{"?? -dev", 3, "?? -dev", "", 4, { 0, 1, 3, 4, -1, -1}, |
|
90, 0}, |
|
{"Abstract File:", 3, "Abstract File: ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"After commit :", 3, "After commit :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"App Id :", 3, "App Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Biblio File :", 3, "Biblio File : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Build timestamp :", 3, "Build timestamp : ", "", 1, |
|
{ 0, -1, -1, -1, -1, -1}, 1, 1}, |
|
{"CopyrightFile:", 3, "CopyrightFile: ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Creation Time:", 3, "Creation Time: ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"DVD obs 64 kB:", 3, "DVD obs 64 kB:", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Drive current:", 3, "Drive current:", "", 2, { 0, 1, -1, -1, -1, -1}, |
|
2, 0}, |
|
{"Drive type :", 3, "Drive type :", "", 3, { 1, 3, 5, -1, -1, -1}, |
|
2, 0}, |
|
{"Eff. Time :", 3, "Eff. Time : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Expir. Time :", 3, "Expir. Time : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Ext. filters :", 3, "Ext. filters : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"File damaged :", 3, "File damaged :", "", 4, { 0, 2, 4, 6, -1, -1}, |
|
10000, 0}, |
|
{"File data lba:", 3, "File data lba:", "", 5, { 0, 2, 4, 6, 8, -1}, |
|
10000, 0}, |
|
{"Format idx :", 3, "Format idx ", ",: ", 4, { 0, 1, 2, 3, -1, -1}, |
|
100, 1}, |
|
{"Format status:", 3, "Format status:", ", ", 2, { 0, 1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"ISO session :", 3, "ISO session :", "", 4, { 0, 2, 4, 6, -1, -1}, |
|
10000, 1}, |
|
{"Image size :", 3, "Image size :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Jigdo files :", 3, "Jigdo files :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Local ACL :", 3, "Local ACL :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Local xattr :", 3, "Local xattr :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"MD5 MISMATCH:", 3, "MD5 MISMATCH:", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
10000, 0}, |
|
{"MD5 tag range:", 3, "MD5 tag range:", "", 3, { 0, 2, 4, -1, -1, -1}, |
|
10000, 1}, |
|
{"Media blocks :", 3, "Media blocks :", "", 3, { 0, 3, 6, -1, -1, -1}, |
|
2, 0}, |
|
{"Media current:", 3, "Media current: ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
2, 1}, |
|
{"Media nwa :", 3, "Media nwa :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Media product:", 3, "Media product:", "", 2, { 0, 2, -1, -1, -1, -1}, |
|
2, 1}, |
|
{"Media region :", 3, "Media region :", "", 3, { 0, 2, 4, -1, -1, -1}, |
|
10000, 1}, |
|
{"Media space :", 3, "Media space :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Media status :", 3, "Media status : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
2, 1}, |
|
{"Media summary:", 3, "Media summary:", "", 4, { 0, 2, 5, 7, -1, -1}, |
|
2, 0}, |
|
{"Modif. Time :", 3, "Modif. Time : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"PVD address :", 3, "PVD address :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Preparer Id :", 3, "Preparer Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Profile :", 3, "Profile :", "", 2, { 0, 1, -1, -1, -1, -1}, |
|
256, 1}, |
|
{"Publisher Id :", 3, "Publisher Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Readline :", 3, "Readline :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Size lower :", 3, "Size lower :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Size upper :", 3, "Size upper :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"System Id :", 3, "System Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Version timestamp :", 3, "Version timestamp :", "", 1, |
|
{ 0, -1, -1, -1, -1, -1}, 1, 0}, |
|
{"Volume Id :", 3, "Volume Id : ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Volume Set Id:", 3, "Volume Set Id: ", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 1}, |
|
{"Volume id :", 3, "Volume id :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
2, 0}, |
|
{"Write speed :", 3, "Write speed :", "", 2, { 0, 2, -1, -1, -1, -1}, |
|
100, 0}, |
|
{"Write speed H:", 3, "Write speed H:", "", 2, { 0, 2, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Write speed L:", 3, "Write speed L:", "", 2, { 0, 2, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Write speed h:", 3, "Write speed h:", "", 2, { 0, 2, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"Write speed l:", 3, "Write speed l:", "", 2, { 0, 2, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"libburn in use :", 3, "libburn in use :", "", 2, |
|
{ 0, 1, -1, -1, -1, -1}, 1, 1}, |
|
{"libburn OS adapter:", 3, "libburn OS adapter: ", "", 1, |
|
{ 0, -1, -1, -1, -1, -1}, 1, 1}, |
|
{"libisoburn in use :", 3, "libisoburn in use :", "", 2, |
|
{ 0, 1, -1, -1, -1, -1}, 1, 1}, |
|
{"libisofs in use :", 3, "libisofs in use :", "", 2, |
|
{ 0, 1, -1, -1, -1, -1}, 1, 1}, |
|
{"libjte in use :", 3, "libjte in use :", "", 2, |
|
{ 0, 1, -1, -1, -1, -1}, 1, 1}, |
|
{"xorriso version :", 3, "xorriso version :", "", 1, |
|
{ 0, -1, -1, -1, -1, -1}, 1, 0}, |
|
{"zisofs :", 3, "zisofs :", "", 1, { 0, -1, -1, -1, -1, -1}, |
|
1, 0}, |
|
{"@", 0, "@", "", 0, {-1, -1, -1, -1, -1, -1}, 0, 0} |
|
}; |
|
|
|
struct Xorriso_sieve_big_filteR *f; |
|
int ret, i; |
|
|
|
for(i= 0; ; i++) { |
|
f= &(filters[i]); |
|
if(strcmp(f->name, "@") == 0) |
|
break; |
|
ret= Xorriso_sieve_add_filter(xorriso, f->name, f->channels, f->prefix, |
|
f->separators, f->num_words, f->word_idx, |
|
f->max_results, f->flag); |
|
if(ret <= 0) |
|
goto failure; |
|
} |
|
return(1); |
|
failure: |
|
Xorriso_sieve_dispose(xorriso, 0); |
|
return(-1); |
|
} |
|
|
|
|
|
/* Check for matching filter and eventually extract words. |
|
To be called by Xorriso_result, Xorriso_info, Xorriso_mark, |
|
and alike. |
|
Thus no own message output is allowed here ! |
|
@param flag bit0-1= channel: |
|
0= result channel |
|
1= info channel |
|
2= mark channel |
|
*/ |
|
int Xorriso_sieve_filter_msg(struct XorrisO *xorriso, char *msg, int flag) |
|
{ |
|
int channel, ret, argc= 0, i, max_words, l, widx, skip; |
|
char **argv= NULL, *prefix_storage= NULL, *prefix, *cpt, *to_parse= NULL; |
|
struct Xorriso_msg_filteR *f; |
|
struct Xorriso_lsT *lst, *prev_lst, *next_lst; |
|
|
|
if(xorriso->msg_sieve == NULL || xorriso->msg_sieve_disabled) |
|
return(1); |
|
|
|
channel= flag & 3; |
|
|
|
for(f= xorriso->msg_sieve->first_filter; f != NULL; f= f->next) { |
|
if(!(f->channels & (1 << channel))) |
|
continue; |
|
prefix= f->prefix; |
|
|
|
if(prefix[0] == '?') { |
|
skip= 0; |
|
for(cpt= prefix; *cpt; cpt++) |
|
if(*cpt == '?') |
|
skip++; |
|
else |
|
break; |
|
l= strlen(prefix); |
|
if(strlen(msg) >= (unsigned int) l) { |
|
if(l - skip == 0 || strncmp(prefix + skip, msg + skip, l - skip) == 0) { |
|
Xorriso_alloc_meM(prefix_storage, char, l + 1); |
|
strncpy(prefix_storage, msg, l); |
|
prefix_storage[l]= 0; |
|
prefix= prefix_storage; |
|
} |
|
} |
|
} |
|
if(prefix[0]) |
|
if(strncmp(prefix, msg, strlen(prefix)) != 0) |
|
continue; |
|
|
|
to_parse= strdup(msg); |
|
if(to_parse == NULL) |
|
goto no_mem; |
|
l= strlen(to_parse); |
|
if(l > 0) |
|
if(to_parse[l - 1] == '\n') |
|
to_parse[l - 1]= 0; |
|
|
|
max_words= 0; |
|
if(f->last_word_line_end) |
|
if(f->num_words > 0) /* Let last word take rest of line */ |
|
max_words= f->word_idx[f->num_words - 1]; |
|
if(max_words <= 0 && f->last_word_line_end) { |
|
/* Copy rest of line as single word because Xorriso_parse_line understands |
|
max_words == 0 as unlimited number of words. But here it is desired |
|
to get the rest of line already in argv[0]. |
|
*/ |
|
max_words= 0; |
|
argv= calloc(1, sizeof(char *)); |
|
if(argv == NULL) |
|
goto no_mem; |
|
argc= 1; |
|
argv[0]= strdup(to_parse + strlen(prefix)); |
|
if(argv[0] == NULL) |
|
goto no_mem; |
|
ret= 1; |
|