libisoburn/xorriso/text_io.c

4696 lines
143 KiB
C

/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
Copyright 2007-2016 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 **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;
char *cpt= NULL;
#endif /* Xorriso_with_line_editoR */
double tdiff;
struct timeval tv;
struct Xorriso_lsT *next_lst;
gettimeofday(&tv, NULL);
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 | 2))) {
/* 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:;
#ifdef Xorriso_with_line_editoR
if(cpt!=NULL)
free(cpt);
#endif
gettimeofday(&tv, NULL);
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 something 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)
goto ex;
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)
goto ex;
locked= 1;
if(xorriso->msglist_stackfill + 1 >= Xorriso_max_outlist_stacK) {
Xorriso_unlock_outlists(xorriso, 0);
locked= 0;
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)
goto ex;
locked= 1;
if(stack_handle == -1)
stack_handle= xorriso->msglist_stackfill - 1;
if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) {
Xorriso_unlock_outlists(xorriso, 0);
locked= 0;
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)
goto ex;
locked= 1;
if(stack_handle == -1)
stack_handle= xorriso->msglist_stackfill - 1;
if(stack_handle < 0 || stack_handle >= xorriso->msglist_stackfill) {
Xorriso_unlock_outlists(xorriso, 0);
locked= 0;
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, lock_failure= 0;
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;
ret= Xorriso_obtain_lock(xorriso, &(xorriso->msgw_fetch_lock),
"message watcher fetch operation", 1);
if(ret <= 0) {
lock_failure= 1;
break;
}
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 &&
!lock_failure)
(*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 acquire 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 acquire 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);
}
ret= Xorriso_obtain_lock(xorriso, &(xorriso->msgw_fetch_lock),
"message watcher fetch operation", 1);
if(ret <= 0) {
Xorriso_msgs_submit(xorriso, 0,
"Cannot obtain mutex lock for managing concurrent message watcher",
ret, "FATAL", 0);
ret= -1;
goto ex;
}
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 */
goto unexpected_null;
}
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 */
unexpected_null:;
Xorriso_msgs_submit(xorriso, 0,
"Program error: Unexpected NULL pointer in message sieve.",
0, "WARNING", 0);
if(*argv != NULL)
Xorriso__dispose_words(argc, argv);
*available= 0;
return(-2);
}
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 id :", 3, "Drive id :", "", 1, { 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 id :", 3, "Media id :", "", 1, { 0, -1, -1, -1, -1, -1},
2, 0},
{"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_free_meM(prefix_storage);
prefix_storage= NULL;
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;
if (to_parse != NULL)
free(to_parse);
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;
} else {
ret= Xorriso_parse_line(xorriso, to_parse, prefix, f->separators,
max_words, &argc, &argv, 0);
}
if(ret < 0)
goto ex;
if(ret == 0)
continue;
if(f->last_word_line_end && argc > max_words) {
l= strlen(argv[max_words]);
if(l > 0)
if(argv[max_words][l - 1] == '\n')
argv[max_words][l - 1]= 0;
}
if(f->max_results > 0 && f->num_results >= f->max_results) {
/* Dispose surplus results */
for(i= 0; i < f->num_words; i++) {
if(f->results != NULL) {
next_lst= f->results->next;
Xorriso_lst_destroy(&(f->results), 0);
f->results= next_lst;
}
}
if(f->num_delivered > 0)
(f->num_delivered)--;
if(f->num_delivered == 0)
f->next_to_deliver= NULL;
f->num_results--;
}
if(f->results == NULL) {
prev_lst= NULL;
} else {
for(prev_lst= f->results; prev_lst->next != NULL;
prev_lst= prev_lst->next);
}
for(i= 0; i < f->num_words; i++) {
widx= f->word_idx[i];
if(widx >= argc || widx < 0)
ret= Xorriso_lst_new(&lst, "", prev_lst, 0);
else if(argv[widx] == NULL)
ret= Xorriso_lst_new(&lst, "", prev_lst, 0);
else
ret= Xorriso_lst_new(&lst, argv[widx], prev_lst, 0);
if(ret <= 0)
goto no_mem;
if(prev_lst == NULL)
f->results= lst;
prev_lst= lst;
}
(f->num_results)++;
Xorriso__dispose_words(&argc, &argv);
}
ret= 1;
ex:
if(to_parse != NULL)
free(to_parse);
Xorriso_free_meM(prefix_storage);
Xorriso__dispose_words(&argc, &argv);
return(ret);
no_mem:;
Xorriso_no_malloc_memory(xorriso, NULL, 1); /* reports to stderr */
ret= -1;
goto ex;
}
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^ Xorriso_msg_sievE ^^^^^^^^^^^^^^^^^^^^^^^^^^ */
int Xorriso_result(struct XorrisO *xorriso, int flag)
/*
bit0= no considerations or computations or dialog. Just put out.
*/
{
int ret, redirected= 0;
if(flag&1)
goto put_it_out;
if(xorriso->request_to_abort)
return(1);
if(xorriso->msglist_stackfill > 0)
if(xorriso->msglist_flags[xorriso->msglist_stackfill - 1] & 1)
redirected= 1;
if(xorriso->result_page_length>0 && !redirected) {
ret= Xorriso_pager(xorriso,xorriso->result_line,2);
if(ret<=0)
return(ret);
if(ret==2)
return(1);
if(xorriso->request_to_abort)
return(1);
}
put_it_out:;
xorriso->bar_is_fresh= 0;
ret= Xorriso_write_to_channel(xorriso, xorriso->result_line, 1,0);
return(ret);
}
int Xorriso_info(struct XorrisO *xorriso, int flag)
/*
bit0= use pager (as with result)
bit1= permission to suppress output
bit2= insist in showing output
*/
{
int ret;
static int note_sev= 0;
if(flag&2)
if(xorriso->request_to_abort)
return(1);
if(note_sev==0)
Xorriso__text_to_sev("NOTE", &note_sev, 0);
if(note_sev<xorriso->report_about_severity &&
note_sev<xorriso->abort_on_severity && !(flag&4))
return(1);
if(flag&1) {
ret= Xorriso_pager(xorriso,xorriso->info_text,2);
if(ret<=0)
return(ret);
if(ret==2)
return(1);
if(flag&2)
if(xorriso->request_to_abort)
return(1);
}
xorriso->bar_is_fresh= 0;
ret=Xorriso_write_to_channel(xorriso, xorriso->info_text, 2, 0);
return(ret);
}
int Xorriso_mark(struct XorrisO *xorriso, int flag)
{
int ret= 1,r_ret,i_ret;
if(xorriso->mark_text[0]==0)
return(1);
if(xorriso->packet_output)
ret=Xorriso_write_to_channel(xorriso, xorriso->mark_text, 3, 0);
else {
sprintf(xorriso->result_line,"%s\n",xorriso->mark_text);
r_ret= Xorriso_result(xorriso,1);
strcpy(xorriso->info_text,xorriso->result_line);
i_ret= Xorriso_info(xorriso,0);
if(r_ret==0 || i_ret==0)
ret= 0;
}
return(ret);
}
int Xorriso_restxt(struct XorrisO *xorriso, char *text)
{
int ret;
strncpy(xorriso->result_line,text,sizeof(xorriso->result_line)-1);
xorriso->result_line[sizeof(xorriso->result_line)-1]= 0;
ret= Xorriso_result(xorriso,0);
return(ret);
}
/* @param flag bit0-7= purpose
0= ERRFILE
1= mark line (only to be put out if enabled)
*/
int Xorriso_process_errfile(struct XorrisO *xorriso,
int error_code, char msg_text[], int os_errno,
int flag)
{
char ttx[41];
int purpose;
if(strlen(msg_text)>SfileadrL)
return(-1);
purpose= flag&255;
if(purpose==1 && !(xorriso->errfile_mode&1))
return(2);
if(xorriso->errfile_fp!=NULL) {
if(purpose==1)
fprintf(xorriso->errfile_fp, "----------------- %s %s\n",
msg_text, Ftimetxt(time(0), ttx, 1));
else
fprintf(xorriso->errfile_fp, "%s\n", msg_text);
fflush(xorriso->errfile_fp);
return(1);
}
if(xorriso->errfile_log[0]==0)
return(1);
if(strcmp(xorriso->errfile_log, "-")==0 ||
strcmp(xorriso->errfile_log, "-R")==0) {
if(purpose==1)
sprintf(xorriso->result_line, "----------------- %s %s\n",
msg_text, Ftimetxt(time(0), ttx, 1));
else
sprintf(xorriso->result_line, "%s\n", msg_text);
Xorriso_result(xorriso, 1);
return(1);
}
if(strcmp(xorriso->errfile_log, "-I") == 0 &&
xorriso->info_text != msg_text) { /* (Beware of stepping on own foot) */
if(purpose==1)
sprintf(xorriso->info_text, "ERRFILE_MARK=%s %s\n",
msg_text, Ftimetxt(time(0), ttx, 1));
else
sprintf(xorriso->info_text, "ERRFILE=%s\n", msg_text);
Xorriso_info(xorriso, 0);
return(1);
}
return(2);
}
#ifdef Xorriso_fetch_with_msg_queueS