8 changed files with 4564 additions and 3 deletions
@ -0,0 +1,291 @@
|
||||
------------------------------------------------------------------------------ |
||||
xorriso-tcltk |
||||
------------------------------------------------------------------------------ |
||||
Copyright (C) 2012, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org |
||||
Provided under GNU GPL version 2 or later. |
||||
------------------------------------------------------------------------------ |
||||
|
||||
xorriso-tcltk is mainly a proof of concept for a frontend that operates |
||||
xorriso in dialog mode. |
||||
|
||||
It exercises several fundamental gestures of communication: |
||||
- connecting via two pipes |
||||
- sending commands |
||||
- receiving replies |
||||
- inquiring the xorriso message sieve |
||||
- using the xorriso parsing service |
||||
|
||||
Note that any other language than Tcl/Tk could be used, if it only can |
||||
do i/o via standard input and standard output or via named pipes. |
||||
Further it has to perform integer arithmetics and string manipulations. |
||||
And, well, a graphical widget set would be nice. |
||||
|
||||
See man xorriso for a documentation of xorriso concepts and commands. |
||||
See man xorrecord for details of the burn image file feature. |
||||
|
||||
|
||||
Quick start: |
||||
|
||||
xorriso -launch_frontend $(which xorriso-tcltk) --stdio -- |
||||
|
||||
|
||||
The Tcl shell "wish" is allergic to options which start by "-h". |
||||
So here is the output of xorriso-tcltk --help : |
||||
------------------------------------------------------------------------ |
||||
Usage: |
||||
xorriso-tcltk [options] |
||||
Options: |
||||
All options must be given with two dashes ("--option") in |
||||
order to distinguish them from any options of the Tcl shell. |
||||
--help |
||||
Print this text and exit. |
||||
--stdio |
||||
Establishes connection to xorriso via stdin and stdout. |
||||
E.g. when letting xorriso start this frontend program: |
||||
xorriso -launch_frontend $(which xorriso-tcltk) --stdio -- |
||||
--named_pipes cmd_fifo reply_fifo |
||||
Establishes connection to a xorriso process started by: |
||||
xorriso -dialog on <cmd_fifo >reply_fifo |
||||
which is then ready for a run of: |
||||
xorriso-tcltk --named_pipes cmd_fifo reply_fifo |
||||
It is important that the parent of xorriso and of this |
||||
tcl/tk frontend opens the named pipe for commands before |
||||
it opens the named pipe for replies. This avoids deadlock. |
||||
--geometry {+|-}X{+|-}Y |
||||
Sets the position of the main window. |
||||
--click_to_focus |
||||
Chooses that input fields and list boxes get the keyboard |
||||
focus only when being clicked by the mouse. |
||||
--auto_focus |
||||
Chooses that the keyboard focus is where the mouse |
||||
pointer is. (Default) |
||||
--log_file path |
||||
Set a file address for logging of xorriso commands and |
||||
reply messages. The log lines will be appended. |
||||
|
||||
Either --stdio or --named_pipes must be given for a program run. |
||||
|
||||
------------------------------------------------------------------------ |
||||
|
||||
|
||||
Overview of GUI elements |
||||
|
||||
The window is separated into three main areas: |
||||
- Connection to xorriso. |
||||
- Management of drives and image files. |
||||
- Inspection, manipulation, and exploitation of xorriso ISO image model. |
||||
|
||||
------------------------------------------------------------------------ |
||||
|
||||
Connection to xorriso |
||||
|
||||
The "End" button leads to the end of frontend and xorriso process. |
||||
|
||||
The ready/busy field indicates whether a xorriso command is being executed |
||||
and the frontend is still waiting for its reply messages. |
||||
|
||||
The "Command:" field can be used to send commands to xorriso. |
||||
|
||||
The "Refresh state display" button causes the other two main areas to update |
||||
their display after manually transmitted commands may have changed the state |
||||
of drives or ISO model. |
||||
|
||||
The "Log pipes" switch controls whether all xorriso commands and replies |
||||
shall be logged to standard error resp. to the file that has been iven |
||||
with program argumen --log_file. Caution: This log is verbous. |
||||
|
||||
The message box displays commands sent to xorriso and messages recieved |
||||
from xorriso. |
||||
Many commands which are emitted by the GUI will hide themselves and their |
||||
replies from this display. |
||||
All event messages with severity WARNING or higher will show up, nevertheless. |
||||
|
||||
The "Recent problem:" field shows the most severe event message that occured |
||||
during the execution of the most recent command. It also displays the most |
||||
recent problem message from the frontend program itself. |
||||
Several commands emitted by the GUI will not clear this display. But any |
||||
manually transmitted command and the major GUI gestures will do. |
||||
|
||||
The "Worst problem:" field shows the most severe event message that occured |
||||
since last time the "Clear" button was hit. It will not clear automatically. |
||||
|
||||
|
||||
------------------------------------------------------------------------ |
||||
|
||||
Management of drives and image files |
||||
|
||||
The "Scan for drives" button executes command -devices and puts the list |
||||
of found optical drives into the box underneath the button. |
||||
|
||||
The "Pick input drive" button executes command -indev and obtains some |
||||
information about the medium status. This info is displayed in the |
||||
"Input drive or image" line. |
||||
Further it causes the display of the ISO image model to be updated. |
||||
|
||||
The "Pick output drive" button executes command -outdev and displays the |
||||
related info in the "Output drive or image" line. |
||||
|
||||
The "Pick drive for both roles" button executes command -dev and displays |
||||
info in both "... drive or image" lines. |
||||
|
||||
The "Give up drives" executes commands -indev "" -outdev "" and clears |
||||
both "... drive or image" lines, as well as the ISO model. |
||||
|
||||
The "Calm drives" button executes command -calm_drives which tells the |
||||
aquired optical drives to stop spinning until the next drive activity |
||||
gets triggered. |
||||
|
||||
The "Rollback" button excutes command -rollbackwhich drops all pending |
||||
changes of the ISO model and reloads it from the input drive, if one is |
||||
aquired. |
||||
|
||||
The box underneath these buttons shows the optical drives found by the |
||||
"Can for drives" button. |
||||
A double-click on a drive item has the same effect as button "Pick drive |
||||
for both roles". |
||||
|
||||
The line "Input drive or image" displays address and medium status of |
||||
the input drive. |
||||
Its "Eject" button excutes command -eject "in". |
||||
Editing the drive address and pressing the Return key causes the execution |
||||
of command -indev with the field content as drive address. Use this to |
||||
load the model from ISO image data files on hard disk. |
||||
|
||||
The line "Output drive or image" does about the same for the output drive. |
||||
The text input field can be used to address an existing ISO image data |
||||
file or to address a data file that does not yet exist. In the latter |
||||
case, the ,edium status will be blank. |
||||
|
||||
The "Blank" button executes command -blank "as_needed" on the output drive. |
||||
This also applies to ISO image data files, which will get invalidated by |
||||
a small write operation. |
||||
|
||||
The "Format" button executes -format "as_needed". |
||||
This only applies to real optical drives and s of interest only with DVD-RW |
||||
or BD-R media, which both can be used formatted and unformatted. Other media |
||||
types which mandatorily need formatting will be formatted by the write |
||||
commands. |
||||
|
||||
The "Write ISO session" executes command -commit, which writes a session |
||||
with all pending changes to the output drive. The output drive must be |
||||
either blank or it must be the same as the input drive. |
||||
|
||||
The "Close" switch controls whether command -close "on" is emitted with |
||||
"Write ISO session" or whether -as cdrecord option -multi is omitted with |
||||
"Burn image file:". |
||||
|
||||
The "TAO" switch controls whether an incremental write type shall be |
||||
enforced with write commands. Normally xorriso will decide by medium status |
||||
and job parameters which write type to choose. |
||||
|
||||
The "Defect Mgt" switch controls whether slow and error-prone drive internal |
||||
check reading shall be enabled with formatted BD-R or with BD-RE. |
||||
|
||||
The "Burn image file:" button executes command -as "cdrecord" with the |
||||
content of its text field as disk file address of a data file that is |
||||
to be written to the output drive. |
||||
The medium in the drive may be blank or appendable. |
||||
|
||||
|
||||
------------------------------------------------------------------------ |
||||
|
||||
Inspection, manipulation, and exploitation of xorriso ISO image model |
||||
|
||||
The "Extract to disk:" button executes command -extract with the whole |
||||
tree of the current ISO directory or with the selected items of the box |
||||
underneath "ISO directory:". |
||||
This copies the selected files or directory trees from the input drive |
||||
to the address on hard disk which is given by the text filed right of |
||||
the button. |
||||
|
||||
The "Underneath" switch controls the effective hard disk address of an item |
||||
if the address in the text field points to a directory. If "Underneath" |
||||
is enabled, then the file object from the ISO filesystem will be copied to its |
||||
name underneath the hard disk directory. |
||||
If "Underneath" is disabled then an ISO directory tree item will be merged |
||||
with the disk directory tree at the given address. |
||||
Example: |
||||
Selected are "/iso_dir" and "/iso_file". |
||||
Address for hard disk is "/tmp/from_iso". Switch "Selected" is enabled. |
||||
"Underneath" enabled causes commands: |
||||
-extract /iso_dir /tmp/from_iso/iso_dir |
||||
-extract /iso_file /tmp/from_iso/iso_file |
||||
"Underneath" disabled: |
||||
-extract /iso_dir /tmp/from_iso |
||||
-extract /iso_file /tmp/from_iso |
||||
The last command will fail because /tmp/from_iso already exists as directory. |
||||
|
||||
The "Selected" switch controls whether the whole current ISO directory, |
||||
or only the selected items shall be copied to to hard disk. |
||||
|
||||
The "Overwrite files" switch controls whether existing files may be |
||||
overwritten in the ISO image or by extraction on hard disk. |
||||
The frontend program will only detect the most obvious name collisions, |
||||
but xorriso will reliably refuse to overwrite files if this is banned. |
||||
|
||||
The "Overwrite ISO dirs" switch controls whether it is allowed to replace |
||||
an ISO directory by a non-directory file. |
||||
If a directory is copied to a directory, then both directory trees will |
||||
be merged. So this switch applies only to situations where non-directories |
||||
hit directories. |
||||
|
||||
The "Enforce disk dir write access" switch enables the options "auto_chmod_on" |
||||
and "sort_lba_on". "auto_chmod_on" allows xorriso to give itself temporariy |
||||
w-permission to all disk directories which are owned by the xorriso user. |
||||
This is not without dangers, of course, but comes in handy with restoring of |
||||
backups. |
||||
Option "sort_lba_on" reduces head-moves of optical drives and thus can |
||||
speed up extraction substantially. It is bound to "auto_chmod_on" because |
||||
else it might get in trouble when restoring ISO directories which offer |
||||
no w-permission. |
||||
|
||||
The "Refresh avail:" button triggers a time consuming exact prediction |
||||
of the free space on the medium in the output drive. For this purpose, |
||||
the size of an ISO session with the pending changes is computed. |
||||
With image files rather than real optical drives, the free space of |
||||
the hosting filesystem is displayed. |
||||
|
||||
The "Insert from disk:" button executes command -map with the disk file |
||||
address that is given by the text field right to the button. |
||||
|
||||
The switch "Underneath" has the same effect as with file extraction: |
||||
If enabled, a directory from disk will not be unpacked to its single files |
||||
but put underneath the target address by its own leaf name. |
||||
If the switch "Selected" is enabled, then the given disk file or tree will |
||||
be inserted at or underneath the only selected item in the box inderneath |
||||
"ISO directory:". |
||||
|
||||
The text field in the "ISO directory:" line displays the current ISO |
||||
directory and can be used to toggle its path directly. Hitting the |
||||
Return key causes the current directory to change and the display in |
||||
the box underneath to be refreshed. |
||||
|
||||
The "Up" buttons move the current ISO directory one directory level up. |
||||
|
||||
The "Verify" button executes -md5_check_r "SORRY" with the current ISO |
||||
directory. ISO images bear MD5s for each data file if they were produced |
||||
by xorriso with -md5 "on" resp. -for_backup. This frontend enables this |
||||
feature on startup. |
||||
|
||||
The list box underneath the "ISO directory:" line displays the files in |
||||
the current ISO directory. One or more item can be selected and play a |
||||
role with extraction or insertion of files. |
||||
Most of the buttons underneath the box operate on the selected items |
||||
unconditionally. |
||||
|
||||
The "Verify" button in the "ISO selection:" line executes command |
||||
-md5_check_r "SORRY" with each of the selected items. |
||||
|
||||
The "Delete" button executes command -rm_r with each of the selected items. |
||||
|
||||
The "Rename to:" button iuses command -mv to move each of the selected |
||||
items to the address that is given by the text field right to the button. |
||||
If this address points to an existing ISO directory, then the items will |
||||
be moved underneath that directory and keep their leaf names. |
||||
Else there may be only one selected item which will be renamed to the |
||||
given address. |
||||
|
||||
The "Make dir" button executes command -mkdir with the address in the |
||||
text field to its left (the same as used by "Rename to:"). Useful to |
||||
create a target directory before moving the selection. |
||||
|
@ -0,0 +1,980 @@
|
||||
|
||||
/* Beefed-up example from man 2 pipe
|
||||
to illustrate how xorriso is to be used by frontend programs via two pipes. |
||||
Additionally there is a standalone implementation of Xorriso_parse_line(). |
||||
|
||||
Copyright 2012 Thomas Schmitt, <scdbackup@gmx.net>
|
||||
Unaltered provided under BSD license. |
||||
You may issue licenses of your choice for derived code, provided that they |
||||
do not infringe anybody's right to do the same for this original code. |
||||
|
||||
Build: |
||||
cc -g -o frontend_pipes_xorriso frontend_pipes_xorriso.c |
||||
|
||||
Usage: |
||||
./frontend_pipes_xorriso [path_to_xorriso_binary | -h] |
||||
|
||||
*/ |
||||
|
||||
#include <sys/wait.h> |
||||
#include <assert.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
#include <string.h> |
||||
#include <ctype.h> |
||||
|
||||
|
||||
static int usage() |
||||
{ |
||||
static char helptext[][80] = { |
||||
"usage: frontend_pipes_xorriso [path_to_xorriso|-h]", |
||||
"", |
||||
"Forks a process that runs xorriso and communicates with it via two pipes.", |
||||
"The command pipe sends payload commands and -mark commands. The reply pipe", |
||||
"receives -pkt_output lines which it dispatches to stdout and stderr.", |
||||
"The communication between both processes is made synchronous by the parent", |
||||
"awaiting the -mark message of the child.", |
||||
"Optionally the reply lines can be parsed into words. This is initiated by", |
||||
"meta command", |
||||
" @parse [prefix [separators [max_words [flag]]]]", |
||||
"which sets the four parameters for a function equivalent to", |
||||
"Xorriso_parse_line() (see xorriso.h). All reply will then be parsed and", |
||||
"non-empty word arrays are displayed. Meta command", |
||||
" @noparse", |
||||
"ends this mode.", |
||||
"Meta command", |
||||
" @drain_sieve", |
||||
"reports all recorded results of all installed message sieve filter rules.", |
||||
"For illustration perform this xorriso command sequence", |
||||
" -msg_op start_sieve - -outdev /dev/sr0 -msg_op clear_sieve - -toc", |
||||
"and then @drain_sieve.",
|
||||
"@END@" |
||||
}; |
||||
int i; |
||||
|
||||
for (i = 0; strcmp(helptext[i], "@END@") != 0; i++) |
||||
fprintf(stderr, "%s\n", helptext[i]); |
||||
return(1); |
||||
} |
||||
|
||||
|
||||
/* Local helpers of parent process */ |
||||
|
||||
struct boss_state { |
||||
/* What the parent needs to know about its connection to xorriso */ |
||||
|
||||
/* The ends of the dialog pipes */ |
||||
int command_fd; |
||||
int reply_fd; |
||||
|
||||
/* For synchronization between boss and xorriso */ |
||||
int mark_count; |
||||
char pending_mark[16]; |
||||
|
||||
/* Parsing_parameters. See xorriso.h Xorriso_parse_line */ |
||||
int do_parse; |
||||
char progname[1024]; |
||||
char prefix[1024]; |
||||
char separators[256]; |
||||
int max_words; |
||||
int flag; |
||||
|
||||
/* A primitive catcher for result lines */ |
||||
int reply_lines_size; /* 0= catching disabled */ |
||||
char **reply_lines; |
||||
int reply_lines_count; |
||||
}; |
||||
|
||||
#define Frontend_xorriso_max_resulT 1000 |
||||
|
||||
|
||||
/* Some basic gestures of this program: */ |
||||
|
||||
static int prompt_for_command(struct boss_state *boss, |
||||
char *line, int line_size); |
||||
|
||||
static int transmit_command(struct boss_state *boss, char *line); |
||||
|
||||
static int await_all_replies(struct boss_state *boss); |
||||
|
||||
static int de_pkt_result(struct boss_state *boss); |
||||
|
||||
static int drain_sieve(struct boss_state *boss); |
||||
|
||||
int parse_line(char *progname, char *line, |
||||
char *prefix, char *separators, int max_words, |
||||
int *argc, char ***argv, int flag); |
||||
|
||||
int dispose_parsed_words(int *argc, char ***argv); |
||||
|
||||
|
||||
|
||||
/* Parent and child */ |
||||
int main(int argc, char *argv[]) |
||||
{ |
||||
int command_pipe[2], reply_pipe[2]; |
||||
pid_t cpid; |
||||
char *xorriso_path = "/usr/bin/xorriso"; |
||||
|
||||
if (argc > 1) { |
||||
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0 || |
||||
strcmp(argv[1], "--help") == 0) { |
||||
usage(); |
||||
exit(0); |
||||
} |
||||
xorriso_path = argv[1]; |
||||
} |
||||
|
||||
if (pipe(command_pipe) == -1) |
||||
{ perror("pipe"); exit(1); } |
||||
if (pipe(reply_pipe) == -1) |
||||
{ perror("pipe"); exit(1); } |
||||
|
||||
cpid = fork(); |
||||
if (cpid == -1) |
||||
{ perror("fork"); exit(2); } |
||||
|
||||
if (cpid == 0) { |
||||
/* Child redirects stdin and stdout. Then it becomes xorriso. */ |
||||
|
||||
char *xargv[8]; |
||||
|
||||
close(command_pipe[1]); /* Close unused write end */ |
||||
close(reply_pipe[0]); /* Close unused read end */ |
||||
|
||||
/* Attach pipe ends to stdin and stdout */ |
||||
close(0); |
||||
if (dup2(command_pipe[0], 0) == -1) |
||||
{ perror("dup2(,0)"); exit(1); } |
||||
close(1); |
||||
if (dup2(reply_pipe[1], 1) == -1) |
||||
{ perror("dup2(,1)"); exit(1); } |
||||
|
||||
xargv[0] = xorriso_path; |
||||
xargv[1] = "-dialog"; |
||||
xargv[2] = "on"; |
||||
xargv[3] = "-pkt_output"; |
||||
xargv[4] = "on"; |
||||
xargv[5] = "-mark"; |
||||
xargv[6] = "0"; /* corresponds to mark_count = 0 in parent */ |
||||
xargv[7] = NULL; |
||||
execv(xorriso_path, xargv); |
||||
perror("execv"); exit(1); |
||||
|
||||
} else { |
||||
/* Parent prompts user for command lines and prints xorriso replies.
|
||||
It knows when all reply text of the pending command line has arrived |
||||
by watching for -mark reply pending_mark.
|
||||
*/ |
||||
|
||||
int ret; |
||||
char line[4096]; |
||||
struct boss_state boss; |
||||
|
||||
close(command_pipe[0]); /* Close unused read end */ |
||||
close(reply_pipe[1]); /* Close unused write end */ |
||||
|
||||
memset(&boss, 0, sizeof(boss)); |
||||
boss.command_fd = command_pipe[1]; |
||||
boss.reply_fd = reply_pipe[0]; |
||||
strcpy(boss.progname, argv[0]); |
||||
boss.reply_lines = NULL; |
||||
|
||||
/* Dialog loop */ |
||||
sprintf(boss.pending_mark, "%d", boss.mark_count); |
||||
while (1) { |
||||
|
||||
/* Wait for pending mark and print all replies */ |
||||
ret = await_all_replies(&boss); |
||||
if (ret < 0) |
||||
break; |
||||
|
||||
/* Prompt for command line */ |
||||
ret = prompt_for_command(&boss, line, sizeof(line)); |
||||
if (ret <= 0) |
||||
break; |
||||
|
||||
/* Send line and -mark command */ |
||||
ret = transmit_command(&boss, line); |
||||
if (ret <= 0) |
||||
break; |
||||
} |
||||
|
||||
|
||||
/* >>> if child is still operational: send -rollback_end */; |
||||
|
||||
/* >>> wait a short while */; |
||||
|
||||
/* >>> if not yet ended: kill child */; |
||||
|
||||
wait(NULL); /* Wait for child */ |
||||
exit(0); |
||||
} |
||||
} |
||||
|
||||
|
||||
/* ------------------- Local helpers of parent process -------------------- */ |
||||
|
||||
static int show_parsed(struct boss_state *boss, char *line); |
||||
static int record_reply_line(struct boss_state *boss, char *line); |
||||
static int make_reply_lines(struct boss_state *boss); |
||||
static int input_interpreter(char *line, struct boss_state *boss); |
||||
|
||||
|
||||
/* Ask the user for command input and trigger processing of meta commands.
|
||||
*/ |
||||
static int prompt_for_command(struct boss_state *boss, |
||||
char *line, int line_size) |
||||
{ |
||||
int l, ret; |
||||
char *line_res; |
||||
|
||||
while (1) { |
||||
fprintf(stderr, "+++ Enter a command and its parameters :\n"); |
||||
line_res = fgets(line, line_size - 1, stdin); |
||||
if (line_res == NULL) |
||||
return(0); |
||||
l = strlen(line); |
||||
if (l == 0) { |
||||
line[0] = '\n'; |
||||
line[1] = 0; |
||||
} else if (line[l - 1] != '\n') { |
||||
line[l] = '\n'; |
||||
line[l + 1] = 0; |
||||
} |
||||
/* Interpret meta commands which begin by @ */ |
||||
ret = input_interpreter(line, boss); |
||||
if (ret == 0) |
||||
return(1); |
||||
if (ret < 0) |
||||
return(-1); |
||||
} |
||||
} |
||||
|
||||
|
||||
/* Transmit a command (which must end by white space, e.g. newline)
|
||||
and its unique synchronization mark. |
||||
*/ |
||||
static int transmit_command(struct boss_state *boss, char *line) |
||||
{ |
||||
int ret; |
||||
char mark_line[32]; |
||||
|
||||
ret = write(boss->command_fd, line, strlen(line)); |
||||
if (ret == -1) { |
||||
perror("write"); |
||||
return(0); |
||||
} |
||||
/* Produce new unique -mark text to watch for */ |
||||
(boss->mark_count)++; |
||||
sprintf(boss->pending_mark, "%d", boss->mark_count); |
||||
sprintf(mark_line, "-mark %s\n", boss->pending_mark); |
||||
ret = write(boss->command_fd, mark_line, strlen(mark_line)); |
||||
if (ret == -1) { |
||||
perror("write"); |
||||
return(0); |
||||
} |
||||
return(1); |
||||
} |
||||
|
||||
|
||||
/* Read reply messages from xorriso and wait for the expected synchronization
|
||||
mark. Messages can be printed or collected in boss->reply_lines. |
||||
*/ |
||||
static int await_all_replies(struct boss_state *boss) |
||||
{ |
||||
int count, remainder = 0, ret; |
||||
char buf[32769], *line, *npt; |
||||
|
||||
while (1) { |
||||
count = read(boss->reply_fd, buf + remainder, |
||||
sizeof(buf) - 1 - remainder); |
||||
if (count == -1) { |
||||
perror("read"); |
||||
return(-1); |
||||
} |
||||
if (count == 0) { |
||||
fprintf(stderr, "+++ EOF encounterd by Master process\n"); |
||||
return(-2); |
||||
} |
||||
for (npt = buf + remainder; npt < buf + count; npt++) { |
||||
if (*npt == 0) { |
||||
fprintf(stderr, |
||||
"+++ Protocol error : Reply contains 0-chars\n"); |
||||
return(-1); |
||||
} |
||||
} |
||||
|
||||
/* Split buf into lines */ |
||||
buf[remainder + count] = 0; /* for convenience */ |
||||
line = buf; |
||||
while (1) { |
||||
npt = strchr(line, '\n'); |
||||
if (npt == NULL) { |
||||
/* Move line to start of buffer and set remainder */ |
||||
if (line != buf) { |
||||
remainder = 0; |
||||
for (npt = line; *npt; npt++) |
||||
buf[remainder++] = *npt; |
||||
} |
||||
/* Now read more data in the hope to get a newline char */ |
||||
break; |
||||
} |
||||
/* Interpret line */ |
||||
*npt = 0; |
||||
if (line[0] == 'M') { |
||||
/* M-replies will be outdated until the pending command line
|
||||
is completely done and the appended -mark command gets |
||||
into effect. |
||||
*/ |
||||
if (strlen(line) < 6) { |
||||
fprintf(stderr, |
||||
"+++ Protocol error : M-channel line shorter than 6 chars\n"); |
||||
return(-1); |
||||
} |
||||
if (strcmp(line + 5, boss->pending_mark) == 0) { |
||||
if ((line - buf) + strlen(line) + 1 < count) { |
||||
fprintf(stderr, |
||||
"+++ Protocol error : Surplus reply data after M-match\n"); |
||||
fprintf(stderr, "%s\n", line + strlen(line) + 1); |
||||
return(-1); |
||||
} |
||||
return (1); /* Expected mark has arrived */ |
||||
} |
||||
} else if (line[0] == 'R') { |
||||
/* R-replies are result lines of inquiry commands, like -ls.
|
||||
They should be handled by specialized code which knows |
||||
how to parse and interpret them. |
||||
*/ |
||||
if (boss->reply_lines_count < boss->reply_lines_size) { |
||||
ret = record_reply_line(boss, line); |
||||
if (ret <= 0) |
||||
return(ret); |
||||
} else |
||||
printf("%s\n", line); |
||||
} else { |
||||
/* I-replies are pacifiers, notifications, warnings, or
|
||||
error messages. They should be handled by a general |
||||
message interpreter which determines their severity |
||||
and decides whether to bother the user. |
||||
*/ |
||||
if (boss->reply_lines_count < boss->reply_lines_size) { |
||||
ret = record_reply_line(boss, line); |
||||
if (ret <= 0) |
||||
return(ret); |
||||
} else |
||||
fprintf(stderr, "%s\n", line); |
||||
} |
||||
|
||||
/* Parse line and show words */ |
||||
if (strlen(line) >= 5) |
||||
show_parsed(boss, line + 5); |
||||
|
||||
line = npt + 1; |
||||
} |
||||
} |
||||
return(1); |
||||
} |
||||
|
||||
|
||||
/* Throw away I channel.
|
||||
Unpack and reconstruct payload of R channel lines. |
||||
*/ |
||||
static int de_pkt_result(struct boss_state *boss) |
||||
{ |
||||
int i, l, w; |
||||
char *payload = NULL, *new_payload = NULL; |
||||
|
||||
w = 0; |
||||
for (i = 0; i < boss->reply_lines_count; i++) { |
||||
if (boss->reply_lines[i][0] != 'R' || |
||||
strlen(boss->reply_lines[i]) < 5) |
||||
continue; |
||||
|
||||
if (payload == NULL) { |
||||
payload = strdup(boss->reply_lines[i] + 5); |
||||
} else { |
||||
l = strlen(payload); |
||||
new_payload = calloc(l + strlen(boss->reply_lines[i] + 5) + 1, 1); |
||||
if (new_payload == NULL) |
||||
goto no_mem; |
||||
strcpy(new_payload, payload); |
||||
strcpy(new_payload + l, boss->reply_lines[i] + 5); |
||||
free(payload); |
||||
payload = new_payload; |
||||
} |
||||
if (payload == NULL) |
||||
goto no_mem; |
||||
l = strlen(payload); |
||||
if (l > 0) |
||||
if (payload[l - 1] == '\n') |
||||
payload[l - 1] = 0; |
||||
|
||||
if (boss->reply_lines[i][2] != '0') { |
||||
free(boss->reply_lines[w]); |
||||
boss->reply_lines[w] = payload; |
||||
w++; |
||||
payload = NULL; |
||||
} |
||||
} |
||||
for (i = w ; i < boss->reply_lines_count; i++) { |
||||
free(boss->reply_lines[i]); |
||||
boss->reply_lines[i] = NULL; |
||||
} |
||||
boss->reply_lines_count = w; |
||||
return(1); |
||||
no_mem:; |
||||
fprintf(stderr, "FATAL: Out of memory !\n"); |
||||
return(-1); |
||||
} |
||||
|
||||
|
||||
/* Inquire and print all recorded message sieve results.
|
||||
*/ |
||||
static int drain_sieve(struct boss_state *boss) |
||||
{ |
||||
int ret, i, j, names_size = 0, names_count = 0, first_result; |
||||
int number_of_strings, available, xorriso_ret, number_of_lines, k, r; |
||||
char **names = NULL, line[1024]; |
||||
|
||||
/* Install catcher for reply_lines */ |
||||
ret = make_reply_lines(boss); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
boss->reply_lines_size = Frontend_xorriso_max_resulT; |
||||
boss->reply_lines_count = 0; |
||||
|
||||
/* Get list of filter rule names from -msg_op show_sieve */ |
||||
ret = transmit_command(boss, "-msg_op show_sieve -\n"); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
ret = await_all_replies(boss); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
ret = de_pkt_result(boss); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
|
||||
names = boss->reply_lines; |
||||
boss->reply_lines = NULL; |
||||
names_size = Frontend_xorriso_max_resulT; |
||||
names_count= boss->reply_lines_count; |
||||
ret = make_reply_lines(boss); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
boss->reply_lines_size = Frontend_xorriso_max_resulT; |
||||
|
||||
/* Inquire caught results of each name by -msg_op read_sieve
|
||||
until return value is <= 0 |
||||
*/ |
||||
printf("--------------------------------------------------\n"); |
||||
for (i = 0; i < names_count; i++) { |
||||
available = 1; |
||||
first_result = 1; |
||||
while (available > 0) { |
||||
boss->reply_lines_count = 0; |
||||
sprintf(line, "-msg_op read_sieve '%s'\n", names[i]); |
||||
ret = transmit_command(boss, line); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
ret = await_all_replies(boss); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
ret = de_pkt_result(boss); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
|
||||
if (boss->reply_lines_count < 2) { |
||||
fprintf(stderr, "drain_sieve: illegible result reply\n"); |
||||
{ret= 0; goto ex;} |
||||
} |
||||
xorriso_ret = -1; |
||||
sscanf(boss->reply_lines[0], "%d", &xorriso_ret); |
||||
if(xorriso_ret <= 0) |
||||
break; |
||||
number_of_strings = -1; |
||||
sscanf(boss->reply_lines[1], "%d", &number_of_strings); |
||||
if(xorriso_ret < 0) |
||||
break; |
||||
if (first_result) |
||||
printf(" '%s' |\n", names[i]); |
||||
first_result = 0; |
||||
for (j = 0; names[i][j] != 0; j++) |
||||
printf("-"); |
||||
printf("-----\n"); |
||||
r = 2; |
||||
for (j = 0; j < number_of_strings && r < boss->reply_lines_count; |
||||
j++) { |
||||
number_of_lines = -1; |
||||
sscanf(boss->reply_lines[r], "%d", &number_of_lines); |
||||
r++; |
||||
printf("|"); |
||||
for (k = 0; k < number_of_lines |
||||
&& r < boss->reply_lines_count; k++) { |
||||
printf("%s%s", boss->reply_lines[r], |
||||
k < number_of_lines - 1 ? "\n" : ""); |
||||
r++; |
||||
} |
||||
printf("|\n"); |
||||
} |
||||
} |
||||
if (first_result == 0) |
||||
printf("--------------------------------------------------\n"); |
||||
} |
||||
|
||||
/* Dispose all recorded results */ |
||||
ret = transmit_command(boss, "-msg_op clear_sieve -\n"); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
ret = await_all_replies(boss); |
||||
if (ret <= 0) |
||||
goto ex; |
||||
|
||||
ret = 1; |
||||
ex:; |
||||
/* Disable result catcher */ |
||||
boss->reply_lines_size = 0; |
||||
if (names != NULL) |
||||
dispose_parsed_words(&names_size, &names); |
||||
return(ret); |
||||
} |
||||
|
||||
|
||||
/* ------------------------- Helpers of local helpers ---------------------- */ |
||||
|
||||
|
||||
static int show_parsed(struct boss_state *boss, char *line) |
||||
{ |
||||
int argc, ret = 0, i; |
||||
char **argv = NULL; |
||||
|
||||
if (!boss->do_parse) |
||||
return(2); |
||||
ret = parse_line(boss->progname, line, boss->prefix, boss->separators, |
||||
boss->max_words, &argc, &argv, boss->flag); |
||||
if (ret <= 0 || argc <= 0) |
||||
return(0); |
||||
fprintf(stderr, "-----------------------------------------------------\n"); |
||||
fprintf(stderr, "parse_line returns %d, argc = %d\n", ret, argc); |
||||
for (i = 0; i < argc; i++) |
||||
fprintf(stderr, "%2d : %s\n", i, argv[i]); |
||||
fprintf(stderr, "-----------------------------------------------------\n"); |
||||
dispose_parsed_words(&argc, &argv); /* release memory */ |
||||
return(1);
|
||||
} |
||||
|
||||
|
||||
static int make_reply_lines(struct boss_state *boss) |
||||
{ |
||||
int i; |
||||
|
||||
if (boss->reply_lines != NULL) |
||||
return(1); |
||||
|
||||
boss->reply_lines = calloc(Frontend_xorriso_max_resulT, |
||||
sizeof(char *)); |
||||
if (boss->reply_lines == 0) { |
||||
fprintf(stderr, "FATAL: Out of memory !\n"); |
||||
return(-1); |
||||
} |
||||
boss->reply_lines_count = 0; |
||||
boss->reply_lines_size = 0; |
||||
for (i = 0; i < Frontend_xorriso_max_resulT; i++) |
||||
boss->reply_lines[i] = NULL; |
||||
return(1); |
||||
} |
||||
|
||||
|
||||
static int record_reply_line(struct boss_state *boss, char *line) |
||||
{ |
||||
if (boss->reply_lines[boss->reply_lines_count] != NULL) |
||||
free(boss->reply_lines[boss->reply_lines_count]); |
||||
boss->reply_lines[boss->reply_lines_count] = strdup(line); |
||||
if (boss->reply_lines[boss->reply_lines_count] == NULL) { |
||||
fprintf(stderr, "FATAL: Out of memory !\n"); |
||||
return(-1); |
||||
} |
||||
boss->reply_lines_count++; |
||||
return(1); |
||||
} |
||||
|
||||
|
||||
static int input_interpreter(char *line, struct boss_state *boss) |
||||
{ |
||||
int argc, ret = 0; |
||||
char **argv = NULL; |
||||
|
||||
ret = parse_line(boss->progname, line, "", "", 6, &argc, &argv, 0); |
||||
if (ret <= 0 || argc <= 0) |
||||
return(0); |
||||
if (strcmp(argv[0], "@parse") == 0) { |
||||
boss->do_parse = 1; |
||||
boss->prefix[0] = 0; |
||||
if (argc > 1) |
||||
strcpy(boss->prefix, argv[1]); |
||||
boss->separators[0] = 0; |
||||
if (argc > 2) |
||||
strcpy(boss->separators, argv[2]); |
||||
boss->max_words = 0; |
||||
if (argc > 3) |
||||
sscanf(argv[3], "%d", &(boss->max_words)); |
||||
boss->max_words = 0; |
||||
if (argc > 4) |
||||
sscanf(argv[4], "%d", &(boss->flag)); |
||||
ret = 1; |
||||
} else if(strcmp(argv[0], "@noparse") == 0) { |
||||
boss->do_parse = 0; |
||||
ret = 1; |
||||
} else if(strcmp(argv[0], "@drain_sieve") == 0) { |
||||
ret= drain_sieve(boss); |
||||
} else { |
||||
ret = 0; |
||||
} |
||||
dispose_parsed_words(&argc, &argv); /* release memory */ |
||||
return ret; |
||||
} |
||||
|
||||
|
||||
/* -------- Line-to-word parser equivalent to Xorriso_parse_line() -------- */ |
||||
|
||||
|
||||
static int Sfile_sep_make_argv(char *progname, char *line, char *separators, |
||||
int max_words, int *argc, char ***argv, int flag); |
||||
|
||||
|
||||
int parse_line(char *progname, char *line, |
||||
char *prefix, char *separators, int max_words, |
||||
int *argc, char ***argv, int flag) |
||||
{ |
||||
int ret, bsl_mode; |
||||
char *to_parse; |
||||
|
||||
*argc = 0; |
||||
*argv = NULL; |
||||
|
||||
to_parse = line; |
||||
bsl_mode = (flag >> 1) & 15; |
||||
if (prefix[0]) { |
||||
if (strncmp(line, prefix, strlen(prefix)) == 0) { |
||||
to_parse = line + strlen(prefix); |
||||
} else { |
||||
ret = 2; goto ex; |
||||
} |
||||
} |
||||
ret = Sfile_sep_make_argv(progname, to_parse, separators, |
||||
max_words, argc, argv, |
||||
(!(flag & 32)) | 4 | (bsl_mode << 5)); |
||||
if (ret < 0) { |
||||
fprintf(stderr, |
||||
"%s : Severe lack of resources during command line parsing\n", |
||||
progname); |
||||
goto ex; |
||||
} |
||||
if (ret == 0) { |
||||
fprintf(stderr, |
||||
"%s : Incomplete quotation in %s line: %s\n", |
||||
progname, (flag & 32) ? "command" : "parsed", to_parse); |
||||
goto ex; |
||||
} |
||||
ex:; |
||||
if (ret <= 0) |
||||
Sfile_sep_make_argv("", "", "", 0, argc, argv, 2); /* release memory */ |
||||
return(ret); |
||||
} |
||||
|
||||
|
||||
int dispose_parsed_words(int *argc, char ***argv) |
||||
{ |
||||
Sfile_sep_make_argv("", "", "", 0, argc, argv, 2); |
||||
return(1); |
||||
} |
||||
|
||||
|
||||
/* -------------- Some helpers copied from xorriso/sfile.c ----------------- */ |
||||
|
||||
|
||||
static int Sfile_destroy_argv(int *argc, char ***argv, int flag) |
||||
{ |
||||
int i; |
||||
|
||||
if(*argc>0 && *argv!=NULL){ |
||||
for(i=0;i<*argc;i++){ |
||||
if((*argv)[i]!=NULL) |
||||
free((*argv)[i]); |
||||
} |
||||
free((char *) *argv); |
||||
} |
||||
*argc= 0; |
||||
*argv= NULL; |
||||
return(1); |
||||
} |
||||
|
||||
|
||||
/* Converts backslash codes into single characters:
|
||||
\a BEL 7 , \b BS 8 , \e ESC 27 , \f FF 12 , \n LF 10 , \r CR 13 , |
||||
\t HT 9 , \v VT 11 , \\ \ 92
|
||||
\[0-9][0-9][0-9] octal code , \x[0-9a-f][0-9a-f] hex code , |
||||
\cX control-x (ascii(X)-64) |
||||
@param upto maximum number of characters to examine for backslash. |
||||
The scope of a backslash (0 to 3 characters) is not affected. |
||||
@param eaten returns the difference in length between input and output |
||||
@param flag bit0= only determine *eaten, do not convert |
||||
bit1= allow to convert \000 to binary 0
|
||||
*/ |
||||
static int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag) |
||||
{ |
||||
char *rpt, *wpt, num_text[8], wdummy[8]; |
||||
unsigned int num= 0; |
||||
|
||||
*eaten= 0; |
||||
wpt= text; |
||||
for(rpt= text; *rpt != 0 && rpt - text < upto; rpt++) { |
||||
if(flag & 1) |
||||
wpt= wdummy; |
||||
if(*rpt == '\\') { |
||||
rpt++; |
||||
(*eaten)++; |
||||
if(*rpt == 'a') { |
||||
*(wpt++)= 7; |
||||
} else if(*rpt == 'b') { |
||||
*(wpt++)= 8; |
||||
} else if(*rpt == 'e') { |
||||
*(wpt++)= 27; |
||||
} else if(*rpt == 'f') { |
||||
*(wpt++)= 12; |
||||
} else if(*rpt == 'n') { |
||||
*(wpt++)= 10; |
||||
} else if(*rpt == 'r') { |
||||
*(wpt++)= 13; |
||||
} else if(*rpt == 't') { |
||||
*(wpt++)= 9; |
||||
} else if(*rpt == 'v') { |
||||
*(wpt++)= 11; |
||||
} else if(*rpt == '\\') { |
||||
*(wpt++)= '\\'; |
||||
} else if(rpt[0] >= '0' && rpt[0] <= '7' && |
||||
rpt[1] >= '0' && rpt[1] <= '7' && |
||||
rpt[2] >= '0' && rpt[2] <= '7') { |
||||
num_text[0]= '0'; |
||||
num_text[1]= *(rpt + 0); |
||||
num_text[2]= *(rpt + 1); |
||||
num_text[3]= *(rpt + 2); |
||||
num_text[4]= 0; |
||||
sscanf(num_text, "%o", &num); |
||||
if((num > 0 || (flag & 2)) && num <= 255) { |
||||
rpt+= 2; |
||||
(*eaten)+= 2; |
||||
*(wpt++)= num; |
||||
} else |
||||
goto not_a_code; |
||||
} else if(rpt[0] == 'x' && |
||||
((rpt[1] >= '0' && rpt[1] <= '9') || |
||||
(rpt[1] >= 'A' && rpt[1] <= 'F') || |
||||
(rpt[1] >= 'a' && rpt[1] <= 'f')) |
||||
&& |
||||
((rpt[2] >= '0' && rpt[2] <= '9') || |
||||
(rpt[2] >= 'A' && rpt[2] <= 'F') || |
||||
(rpt[2] >= 'a' && rpt[2] <= 'f')) |
||||
) { |
||||
num_text[0]= *(rpt + 1); |
||||
num_text[1]= *(rpt + 2); |
||||
num_text[2]= 0; |
||||
sscanf(num_text, "%x", &num); |
||||
if(num > 0 && num <= 255) { |
||||
rpt+= 2; |
||||
(*eaten)+= 2; |
||||
*(wpt++)= num; |
||||
} else |
||||
goto not_a_code; |
||||
} else if(*rpt == 'c') { |
||||
if(rpt[1] > 64 && rpt[1] < 96) { |
||||
*(wpt++)= rpt[1] - 64; |
||||
rpt++; |
||||
(*eaten)++; |
||||
} else |
||||
goto not_a_code; |
||||
} else { |
||||
not_a_code:; |
||||
*(wpt++)= '\\'; |
||||
rpt--; |
||||
(*eaten)--; |
||||
} |
||||
} else |
||||
*(wpt++)= *rpt; |
||||
} |
||||
*wpt= *rpt; |
||||
return(1); |
||||
} |
||||
|
||||
|
||||
#define SfileadrL 4096 |
||||
|
||||
static int Sfile_sep_make_argv(char *progname, char *line, char *separators, |
||||
int max_words, int *argc, char ***argv, int flag) |
||||
/*
|
||||
bit0= read progname as first argument from line |
||||
bit1= just release argument list argv and return |
||||
bit2= abort with return(0) if incomplete quotes are found |
||||
bit3= eventually prepend missing '-' to first argument read from line |
||||
bit4= like bit2 but only check quote completeness, do not allocate memory |
||||
bit5+6= interpretation of backslashes: |
||||
0= no interpretation, leave unchanged |
||||
1= only inside double quotes |
||||
2= outside single quotes |
||||
3= everywhere |
||||
bit7= append a NULL element to argv |
||||
*/ |
||||
{ |
||||
int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten; |
||||
char *cpt,*start; |
||||
char *buf= NULL; |
||||
|
||||
Sfile_destroy_argv(argc,argv,0); |
||||
if(flag&2) |
||||
{ret= 1; goto ex;} |
||||
|
||||
if(flag & 16) |
||||
flag|= 4; |
||||
bsl_mode= (flag >> 5) & 3; |
||||
|
||||
buf= calloc(strlen(line) + SfileadrL, 1); |
||||
if(buf == NULL) |
||||
{ret= -1; goto ex;} |
||||
for(pass=0;pass<2;pass++) { |
||||
cpt= line-1; |
||||
if(!(flag&1)){ |
||||
argzaehl= line_start_argc= 1; |
||||
if(pass==0) |
||||
maxl= strlen(progname); |
||||
else |
||||
strcpy((*argv)[0],progname); |
||||
} else { |
||||
argzaehl= line_start_argc= 0; |
||||
if(pass==0) maxl= 0; |
||||
} |
||||
while(*(++cpt)!=0){ |
||||
if(*separators) { |
||||
if(strchr(separators, *cpt) != NULL) |
||||
continue; |
||||
} else if(isspace(*cpt)) |
||||
continue; |
||||
start= cpt; |
||||
buf[0]= 0; |
||||
cpt--; |
||||
|
||||
if(max_words > 0 && argzaehl >= max_words && *cpt != 0) { |
||||
/* take uninterpreted up to the end */ |
||||
cpt+= strlen(cpt) - 1; |
||||
} |
||||
|
||||
while(*(++cpt)!=0) { |
||||
if(*separators) { |
||||
if(strchr(separators, *cpt) != NULL) |
||||
break; |
||||
} else if(isspace(*cpt)) |
||||
break; |
||||
if(*cpt=='"'){ |
||||
l= cpt-start; bufl= strlen(buf); |
||||
if(l>0) { |
||||
strncpy(buf + bufl, start, l); buf[bufl + l]= 0; |
||||
if(bsl_mode >= 3) { |
||||
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); |
||||
if(ret <= 0) |
||||
goto ex; |
||||
} |
||||
} |
||||
l= strlen(buf); |
||||
start= cpt+1; |
||||
while(*(++cpt)!=0) if(*cpt=='"') break; |
||||
if((flag&4) && *cpt==0) |
||||
{ret= 0; goto ex;} |
||||
l= cpt-start; bufl= strlen(buf); |
||||
if(l>0) { |
||||
strncpy(buf + bufl, start, l); |
||||
buf[bufl + l]= 0; |
||||
if(bsl_mode >= 1) { |
||||
ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0); |
||||
if(ret <= 0) |
||||
goto ex; |
||||
} |
||||
} |
||||
start= cpt+1; |
||||
}else if(*cpt=='\''){ |
||||
l= cpt-start; bufl= strlen(buf); |
||||
if(l>0) { |
||||
strncpy(buf + bufl, start, l); buf[bufl + l]= 0; |
||||
if(bsl_mode >= 3) { |
||||
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); |
||||
if(ret <= 0) |
||||
goto ex; |
||||
} |
||||
} |
||||
l= strlen(buf); |
||||
start= cpt+1; |
||||
while(*(++cpt)!=0) if(*cpt=='\'') break; |
||||
if((flag&4) && *cpt==0) |
||||
{ret= 0; goto ex;} |
||||
l= cpt-start; bufl= strlen(buf); |
||||
if(l>0) { |
||||
strncat(buf,start,l);buf[bufl+l]= 0; |
||||
if(bsl_mode >= 2) { |
||||
ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0); |
||||
if(ret <= 0) |
||||
goto ex; |
||||
} |
||||
} |
||||
start= cpt+1; |
||||
} |
||||
if(*cpt==0) break; |
||||
} |
||||
l= cpt-start; |
||||
bufl= strlen(buf); |
||||
if(l>0) { |
||||
strncpy(buf + bufl, start, l); buf[bufl + l]= 0; |
||||
if(bsl_mode >= 3) { |
||||
ret= Sfile_bsl_interpreter(buf, l, &eaten, 0); |
||||
if(ret <= 0) |
||||
goto ex; |
||||
} |
||||
} |
||||
l= strlen(buf); |
||||
if(pass==0){ |
||||
if(argzaehl==line_start_argc && (flag&8)) |
||||
if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#') |
||||
l++; |
||||
if(l>maxl) maxl= l; |
||||
}else{ |
||||
strcpy((*argv)[argzaehl],buf); |
||||
if(argzaehl==line_start_argc && (flag&8)) |
||||
if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#') |
||||
sprintf((*argv)[argzaehl],"-%s", buf); |
||||
} |
||||
argzaehl++; |
||||
if(*cpt==0) break; |
||||
} |
||||
if(pass==0){ |
||||
if(flag & 16) |
||||
{ret= 1; goto ex;} |
||||
*argc= argzaehl; |
||||
if(argzaehl>0 || (flag & 128)) { |
||||
*argv= (char **) calloc((argzaehl + !!(flag & 128)), sizeof(char *)); |
||||
if(*argv==NULL) |
||||
{ret= -1; goto ex;} |
||||
} |
||||
for(i=0;i<*argc;i++) { |
||||
(*argv)[i]= (char *) calloc(maxl + 1, 1); |
||||
if((*argv)[i]==NULL) |
||||
{ret= -1; goto ex;} |
||||
} |
||||
if(flag & 128) |
||||
(*argv)[*argc]= NULL; |
||||
} |
||||
} |
||||
ret= 1; |
||||
ex: |
||||
if(buf != NULL) |
||||
free(buf); |
||||
return(ret); |
||||
} |
||||
|
Loading…
Reference in new issue