|
|
|
|
|
|
|
/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
|
|
|
|
|
|
|
|
Copyright 2007-2014 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>
|
|
|
|
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
#endif /* Xorriso_with_readlinE */
|
|
|
|
|
|
|
|
|
|
|
|
#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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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_readlinE
|
|
|
|
static char last_input[SfileadrL]= {""};
|
|
|
|
int no_history= 0;
|
|
|
|
#endif /* ! Xorriso_with_readlinE */
|
|
|
|
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_readlinE
|
|
|
|
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_readlinE
|
|
|
|
|
|
|
|
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= readline("");
|
|
|
|
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_readlinE */
|
|
|
|
|
|
|
|
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_readlinE */
|
|
|
|
|
|
|
|
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_readlinE
|
|
|
|
|
|
|
|
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))) {
|
|
|
|
add_history(line);
|
|
|
|
strncpy(last_input,line,sizeof(last_input)-1);
|
|
|
|
last_input[sizeof(last_input)-1]= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* ! Xorriso_with_readlinE */
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
|