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.
libisoburn/xorriso/text_io.c

4581 lines
139 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 | 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:;
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)
</