libisoburn  1.5.4
About: libisoburn is a frontend for the libraries libburn and libisofs which enables creation and expansion of ISO-9660 filesystems on all media and file types supported by libburn. It implements the API and command interpreter of program xorriso, and installs this program as small dynamically linked binary. xorriso is suitable for incremental data backup and for production of bootable ISO 9660 images. A statically linked version is available as GNU xorriso.
  Fossies Dox: libisoburn-1.5.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

frontend_pipes_xorriso.c
Go to the documentation of this file.
1 
2 /* Beefed-up example from man 2 pipe
3  to illustrate how xorriso is to be used by frontend programs via two pipes.
4  Additionally there is a standalone implementation of Xorriso_parse_line().
5 
6  Copyright 2012 Thomas Schmitt, <scdbackup@gmx.net>
7  Unaltered provided under BSD license.
8  You may issue licenses of your choice for derived code, provided that they
9  do not infringe anybody's right to do the same for this original code.
10 
11  Build:
12  cc -g -o frontend_pipes_xorriso frontend_pipes_xorriso.c
13 
14  Usage:
15  ./frontend_pipes_xorriso [path_to_xorriso_binary | -h]
16 
17 */
18 
19 #include <sys/wait.h>
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <ctype.h>
26 
27 
28 static int usage()
29 {
30  static char helptext[][80] = {
31 "usage: frontend_pipes_xorriso [path_to_xorriso|-h]",
32 "",
33 "Forks a process that runs xorriso and communicates with it via two pipes.",
34 "The command pipe sends payload commands and -mark commands. The reply pipe",
35 "receives -pkt_output lines which it dispatches to stdout and stderr.",
36 "The communication between both processes is made synchronous by the parent",
37 "awaiting the -mark message of the child.",
38 "Optionally the reply lines can be parsed into words. This is initiated by",
39 "meta command",
40 " @parse [prefix [separators [max_words [flag]]]]",
41 "which sets the four parameters for a function equivalent to",
42 "Xorriso_parse_line() (see xorriso.h). All reply will then be parsed and",
43 "non-empty word arrays are displayed. Meta command",
44 " @noparse",
45 "ends this mode.",
46 "Meta command",
47 " @drain_sieve",
48 "reports all recorded results of all installed message sieve filter rules.",
49 "For illustration perform this xorriso command sequence",
50 " -msg_op start_sieve - -outdev /dev/sr0 -msg_op clear_sieve - -toc",
51 "and then @drain_sieve.",
52 "@END@"
53  };
54  int i;
55 
56  for (i = 0; strcmp(helptext[i], "@END@") != 0; i++)
57  fprintf(stderr, "%s\n", helptext[i]);
58  return(1);
59 }
60 
61 
62 /* Local helpers of parent process */
63 
64 struct boss_state {
65  /* What the parent needs to know about its connection to xorriso */
66 
67  /* The ends of the dialog pipes */
69  int reply_fd;
70 
71  /* For synchronization between boss and xorriso */
73  char pending_mark[16];
74 
75  /* Parsing_parameters. See xorriso.h Xorriso_parse_line */
76  int do_parse;
77  char progname[1024];
78  char prefix[1024];
79  char separators[256];
80  int max_words;
81  int flag;
82 
83  /* A primitive catcher for result lines */
84  int reply_lines_size; /* 0= catching disabled */
85  char **reply_lines;
87 };
88 
89 #define Frontend_xorriso_max_resulT 1000
90 
91 
92 /* Some basic gestures of this program: */
93 
94 static int prompt_for_command(struct boss_state *boss,
95  char *line, int line_size);
96 
97 static int transmit_command(struct boss_state *boss, char *line);
98 
99 static int await_all_replies(struct boss_state *boss);
100 
101 static int de_pkt_result(struct boss_state *boss);
102 
103 static int drain_sieve(struct boss_state *boss);
104 
105 int parse_line(char *progname, char *line,
106  char *prefix, char *separators, int max_words,
107  int *argc, char ***argv, int flag);
108 
109 int dispose_parsed_words(int *argc, char ***argv);
110 
111 
112 
113 /* Parent and child */
114 int main(int argc, char *argv[])
115 {
116  int command_pipe[2], reply_pipe[2];
117  pid_t cpid;
118  char *xorriso_path = "/usr/bin/xorriso";
119 
120  if (argc > 1) {
121  if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0 ||
122  strcmp(argv[1], "--help") == 0) {
123  usage();
124  exit(0);
125  }
126  xorriso_path = argv[1];
127  }
128 
129  if (pipe(command_pipe) == -1)
130  { perror("pipe"); exit(1); }
131  if (pipe(reply_pipe) == -1)
132  { perror("pipe"); exit(1); }
133 
134  cpid = fork();
135  if (cpid == -1)
136  { perror("fork"); exit(2); }
137 
138  if (cpid == 0) {
139  /* Child redirects stdin and stdout. Then it becomes xorriso. */
140 
141  char *xargv[8];
142 
143  close(command_pipe[1]); /* Close unused write end */
144  close(reply_pipe[0]); /* Close unused read end */
145 
146  /* Attach pipe ends to stdin and stdout */
147  close(0);
148  if (dup2(command_pipe[0], 0) == -1)
149  { perror("dup2(,0)"); exit(1); }
150  close(1);
151  if (dup2(reply_pipe[1], 1) == -1)
152  { perror("dup2(,1)"); exit(1); }
153 
154  xargv[0] = xorriso_path;
155  xargv[1] = "-dialog";
156  xargv[2] = "on";
157  xargv[3] = "-pkt_output";
158  xargv[4] = "on";
159  xargv[5] = "-mark";
160  xargv[6] = "0"; /* corresponds to mark_count = 0 in parent */
161  xargv[7] = NULL;
162  execv(xorriso_path, xargv);
163  perror("execv"); exit(1);
164 
165  } else {
166  /* Parent prompts user for command lines and prints xorriso replies.
167  It knows when all reply text of the pending command line has arrived
168  by watching for -mark reply pending_mark.
169  */
170 
171  int ret;
172  char line[4096];
173  struct boss_state boss;
174 
175  close(command_pipe[0]); /* Close unused read end */
176  close(reply_pipe[1]); /* Close unused write end */
177 
178  memset(&boss, 0, sizeof(boss));
179  boss.command_fd = command_pipe[1];
180  boss.reply_fd = reply_pipe[0];
181  strcpy(boss.progname, argv[0]);
182  boss.reply_lines = NULL;
183 
184  /* Dialog loop */
185  sprintf(boss.pending_mark, "%d", boss.mark_count);
186  while (1) {
187 
188  /* Wait for pending mark and print all replies */
189  ret = await_all_replies(&boss);
190  if (ret < 0)
191  break;
192 
193  /* Prompt for command line */
194  ret = prompt_for_command(&boss, line, sizeof(line));
195  if (ret <= 0)
196  break;
197 
198  /* Send line and -mark command */
199  ret = transmit_command(&boss, line);
200  if (ret <= 0)
201  break;
202  }
203 
204 
205  /* >>> if child is still operational: send -rollback_end */;
206 
207  /* >>> wait a short while */;
208 
209  /* >>> if not yet ended: kill child */;
210 
211  wait(NULL); /* Wait for child */
212  exit(0);
213  }
214 }
215 
216 
217 /* ------------------- Local helpers of parent process -------------------- */
218 
219 static int show_parsed(struct boss_state *boss, char *line);
220 static int record_reply_line(struct boss_state *boss, char *line);
221 static int make_reply_lines(struct boss_state *boss);
222 static int input_interpreter(char *line, struct boss_state *boss);
223 
224 
225 /* Ask the user for command input and trigger processing of meta commands.
226 */
227 static int prompt_for_command(struct boss_state *boss,
228  char *line, int line_size)
229 {
230  int l, ret;
231  char *line_res;
232 
233  while (1) {
234  fprintf(stderr, "+++ Enter a command and its parameters :\n");
235  line_res = fgets(line, line_size - 1, stdin);
236  if (line_res == NULL)
237  return(0);
238  l = strlen(line);
239  if (l == 0) {
240  line[0] = '\n';
241  line[1] = 0;
242  } else if (line[l - 1] != '\n') {
243  line[l] = '\n';
244  line[l + 1] = 0;
245  }
246  /* Interpret meta commands which begin by @ */
247  ret = input_interpreter(line, boss);
248  if (ret == 0)
249  return(1);
250  if (ret < 0)
251  return(-1);
252  }
253 }
254 
255 
256 /* Transmit a command (which must end by white space, e.g. newline)
257  and its unique synchronization mark.
258 */
259 static int transmit_command(struct boss_state *boss, char *line)
260 {
261  int ret;
262  char mark_line[32];
263 
264  ret = write(boss->command_fd, line, strlen(line));
265  if (ret == -1) {
266  perror("write");
267  return(0);
268  }
269  /* Produce new unique -mark text to watch for */
270  (boss->mark_count)++;
271  sprintf(boss->pending_mark, "%d", boss->mark_count);
272  sprintf(mark_line, "-mark %s\n", boss->pending_mark);
273  ret = write(boss->command_fd, mark_line, strlen(mark_line));
274  if (ret == -1) {
275  perror("write");
276  return(0);
277  }
278  return(1);
279 }
280 
281 
282 /* Read reply messages from xorriso and wait for the expected synchronization
283  mark. Messages can be printed or collected in boss->reply_lines.
284 */
285 static int await_all_replies(struct boss_state *boss)
286 {
287  int count, remainder = 0, ret;
288  char buf[32769], *line, *npt;
289 
290  while (1) {
291  count = read(boss->reply_fd, buf + remainder,
292  sizeof(buf) - 1 - remainder);
293  if (count == -1) {
294  perror("read");
295  return(-1);
296  }
297  if (count == 0) {
298  fprintf(stderr, "+++ EOF encountered by Master process\n");
299  return(-2);
300  }
301  for (npt = buf + remainder; npt < buf + count; npt++) {
302  if (*npt == 0) {
303  fprintf(stderr,
304  "+++ Protocol error : Reply contains 0-chars\n");
305  return(-1);
306  }
307  }
308 
309  /* Split buf into lines */
310  buf[remainder + count] = 0; /* for convenience */
311  line = buf;
312  while (1) {
313  npt = strchr(line, '\n');
314  if (npt == NULL) {
315  /* Move line to start of buffer and set remainder */
316  if (line != buf) {
317  remainder = 0;
318  for (npt = line; *npt; npt++)
319  buf[remainder++] = *npt;
320  }
321  /* Now read more data in the hope to get a newline char */
322  break;
323  }
324  /* Interpret line */
325  *npt = 0;
326  if (line[0] == 'M') {
327  /* M-replies will be outdated until the pending command line
328  is completely done and the appended -mark command gets
329  into effect.
330  */
331  if (strlen(line) < 6) {
332  fprintf(stderr,
333  "+++ Protocol error : M-channel line shorter than 6 chars\n");
334  return(-1);
335  }
336  if (strcmp(line + 5, boss->pending_mark) == 0) {
337  if ((line - buf) + strlen(line) + 1 < count) {
338  fprintf(stderr,
339  "+++ Protocol error : Surplus reply data after M-match\n");
340  fprintf(stderr, "%s\n", line + strlen(line) + 1);
341  return(-1);
342  }
343  return (1); /* Expected mark has arrived */
344  }
345  } else if (line[0] == 'R') {
346  /* R-replies are result lines of inquiry commands, like -ls.
347  They should be handled by specialized code which knows
348  how to parse and interpret them.
349  */
350  if (boss->reply_lines_count < boss->reply_lines_size) {
351  ret = record_reply_line(boss, line);
352  if (ret <= 0)
353  return(ret);
354  } else
355  printf("%s\n", line);
356  } else {
357  /* I-replies are pacifiers, notifications, warnings, or
358  error messages. They should be handled by a general
359  message interpreter which determines their severity
360  and decides whether to bother the user.
361  */
362  if (boss->reply_lines_count < boss->reply_lines_size) {
363  ret = record_reply_line(boss, line);
364  if (ret <= 0)
365  return(ret);
366  } else
367  fprintf(stderr, "%s\n", line);
368  }
369 
370  /* Parse line and show words */
371  if (strlen(line) >= 5)
372  show_parsed(boss, line + 5);
373 
374  line = npt + 1;
375  }
376  }
377  return(1);
378 }
379 
380 
381 /* Throw away I channel.
382  Unpack and reconstruct payload of R channel lines.
383 */
384 static int de_pkt_result(struct boss_state *boss)
385 {
386  int i, l, w;
387  char *payload = NULL, *new_payload = NULL;
388 
389  w = 0;
390  for (i = 0; i < boss->reply_lines_count; i++) {
391  if (boss->reply_lines[i][0] != 'R' ||
392  strlen(boss->reply_lines[i]) < 5)
393  continue;
394 
395  if (payload == NULL) {
396  payload = strdup(boss->reply_lines[i] + 5);
397  } else {
398  l = strlen(payload);
399  new_payload = calloc(l + strlen(boss->reply_lines[i] + 5) + 1, 1);
400  if (new_payload == NULL)
401  goto no_mem;
402  strcpy(new_payload, payload);
403  strcpy(new_payload + l, boss->reply_lines[i] + 5);
404  free(payload);
405  payload = new_payload;
406  }
407  if (payload == NULL)
408  goto no_mem;
409  l = strlen(payload);
410  if (l > 0)
411  if (payload[l - 1] == '\n')
412  payload[l - 1] = 0;
413 
414  if (boss->reply_lines[i][2] != '0') {
415  free(boss->reply_lines[w]);
416  boss->reply_lines[w] = payload;
417  w++;
418  payload = NULL;
419  }
420  }
421  for (i = w ; i < boss->reply_lines_count; i++) {
422  free(boss->reply_lines[i]);
423  boss->reply_lines[i] = NULL;
424  }
425  boss->reply_lines_count = w;
426  return(1);
427 no_mem:;
428  fprintf(stderr, "FATAL: Out of memory !\n");
429  return(-1);
430 }
431 
432 
433 /* Inquire and print all recorded message sieve results.
434 */
435 static int drain_sieve(struct boss_state *boss)
436 {
437  int ret, i, j, names_size = 0, names_count = 0, first_result;
438  int number_of_strings, available, xorriso_ret, number_of_lines, k, r;
439  char **names = NULL, line[1024];
440 
441  /* Install catcher for reply_lines */
442  ret = make_reply_lines(boss);
443  if (ret <= 0)
444  goto ex;
446  boss->reply_lines_count = 0;
447 
448  /* Get list of filter rule names from -msg_op show_sieve */
449  ret = transmit_command(boss, "-msg_op show_sieve -\n");
450  if (ret <= 0)
451  goto ex;
452  ret = await_all_replies(boss);
453  if (ret <= 0)
454  goto ex;
455  ret = de_pkt_result(boss);
456  if (ret <= 0)
457  goto ex;
458 
459  names = boss->reply_lines;
460  boss->reply_lines = NULL;
461  names_size = Frontend_xorriso_max_resulT;
462  names_count= boss->reply_lines_count;
463  ret = make_reply_lines(boss);
464  if (ret <= 0)
465  goto ex;
467 
468  /* Inquire caught results of each name by -msg_op read_sieve
469  until return value is <= 0
470  */
471  printf("--------------------------------------------------\n");
472  for (i = 0; i < names_count; i++) {
473  available = 1;
474  first_result = 1;
475  while (available > 0) {
476  boss->reply_lines_count = 0;
477  sprintf(line, "-msg_op read_sieve '%s'\n", names[i]);
478  ret = transmit_command(boss, line);
479  if (ret <= 0)
480  goto ex;
481  ret = await_all_replies(boss);
482  if (ret <= 0)
483  goto ex;
484  ret = de_pkt_result(boss);
485  if (ret <= 0)
486  goto ex;
487 
488  if (boss->reply_lines_count < 2) {
489  fprintf(stderr, "drain_sieve: illegible result reply\n");
490  {ret= 0; goto ex;}
491  }
492  xorriso_ret = -1;
493  sscanf(boss->reply_lines[0], "%d", &xorriso_ret);
494  if(xorriso_ret <= 0)
495  break;
496  number_of_strings = -1;
497  sscanf(boss->reply_lines[1], "%d", &number_of_strings);
498  if(xorriso_ret < 0)
499  break;
500  if (first_result)
501  printf(" '%s' |\n", names[i]);
502  first_result = 0;
503  for (j = 0; names[i][j] != 0; j++)
504  printf("-");
505  printf("-----\n");
506  r = 2;
507  for (j = 0; j < number_of_strings && r < boss->reply_lines_count;
508  j++) {
509  number_of_lines = -1;
510  sscanf(boss->reply_lines[r], "%d", &number_of_lines);
511  r++;
512  printf("|");
513  for (k = 0; k < number_of_lines
514  && r < boss->reply_lines_count; k++) {
515  printf("%s%s", boss->reply_lines[r],
516  k < number_of_lines - 1 ? "\n" : "");
517  r++;
518  }
519  printf("|\n");
520  }
521  }
522  if (first_result == 0)
523  printf("--------------------------------------------------\n");
524  }
525 
526  /* Dispose all recorded results */
527  ret = transmit_command(boss, "-msg_op clear_sieve -\n");
528  if (ret <= 0)
529  goto ex;
530  ret = await_all_replies(boss);
531  if (ret <= 0)
532  goto ex;
533 
534  ret = 1;
535 ex:;
536  /* Disable result catcher */
537  boss->reply_lines_size = 0;
538  if (names != NULL)
539  dispose_parsed_words(&names_size, &names);
540  return(ret);
541 }
542 
543 
544 /* ------------------------- Helpers of local helpers ---------------------- */
545 
546 
547 static int show_parsed(struct boss_state *boss, char *line)
548 {
549  int argc, ret = 0, i;
550  char **argv = NULL;
551 
552  if (!boss->do_parse)
553  return(2);
554  ret = parse_line(boss->progname, line, boss->prefix, boss->separators,
555  boss->max_words, &argc, &argv, boss->flag);
556  if (ret <= 0 || argc <= 0)
557  return(0);
558  fprintf(stderr, "-----------------------------------------------------\n");
559  fprintf(stderr, "parse_line returns %d, argc = %d\n", ret, argc);
560  for (i = 0; i < argc; i++)
561  fprintf(stderr, "%2d : %s\n", i, argv[i]);
562  fprintf(stderr, "-----------------------------------------------------\n");
563  dispose_parsed_words(&argc, &argv); /* release memory */
564  return(1);
565 }
566 
567 
568 static int make_reply_lines(struct boss_state *boss)
569 {
570  int i;
571 
572  if (boss->reply_lines != NULL)
573  return(1);
574 
576  sizeof(char *));
577  if (boss->reply_lines == 0) {
578  fprintf(stderr, "FATAL: Out of memory !\n");
579  return(-1);
580  }
581  boss->reply_lines_count = 0;
582  boss->reply_lines_size = 0;
583  for (i = 0; i < Frontend_xorriso_max_resulT; i++)
584  boss->reply_lines[i] = NULL;
585  return(1);
586 }
587 
588 
589 static int record_reply_line(struct boss_state *boss, char *line)
590 {
591  if (boss->reply_lines[boss->reply_lines_count] != NULL)
592  free(boss->reply_lines[boss->reply_lines_count]);
593  boss->reply_lines[boss->reply_lines_count] = strdup(line);
594  if (boss->reply_lines[boss->reply_lines_count] == NULL) {
595  fprintf(stderr, "FATAL: Out of memory !\n");
596  return(-1);
597  }
598  boss->reply_lines_count++;
599  return(1);
600 }
601 
602 
603 static int input_interpreter(char *line, struct boss_state *boss)
604 {
605  int argc, ret = 0;
606  char **argv = NULL;
607 
608  ret = parse_line(boss->progname, line, "", "", 6, &argc, &argv, 0);
609  if (ret <= 0 || argc <= 0)
610  return(0);
611  if (strcmp(argv[0], "@parse") == 0) {
612  boss->do_parse = 1;
613  boss->prefix[0] = 0;
614  if (argc > 1)
615  strcpy(boss->prefix, argv[1]);
616  boss->separators[0] = 0;
617  if (argc > 2)
618  strcpy(boss->separators, argv[2]);
619  boss->max_words = 0;
620  if (argc > 3)
621  sscanf(argv[3], "%d", &(boss->max_words));
622  boss->max_words = 0;
623  if (argc > 4)
624  sscanf(argv[4], "%d", &(boss->flag));
625  ret = 1;
626  } else if(strcmp(argv[0], "@noparse") == 0) {
627  boss->do_parse = 0;
628  ret = 1;
629  } else if(strcmp(argv[0], "@drain_sieve") == 0) {
630  ret= drain_sieve(boss);
631  } else {
632  ret = 0;
633  }
634  dispose_parsed_words(&argc, &argv); /* release memory */
635  return ret;
636 }
637 
638 
639 /* -------- Line-to-word parser equivalent to Xorriso_parse_line() -------- */
640 
641 
642 static int Sfile_sep_make_argv(char *progname, char *line, char *separators,
643  int max_words, int *argc, char ***argv, int flag);
644 
645 
646 int parse_line(char *progname, char *line,
647  char *prefix, char *separators, int max_words,
648  int *argc, char ***argv, int flag)
649 {
650  int ret, bsl_mode;
651  char *to_parse;
652 
653  *argc = 0;
654  *argv = NULL;
655 
656  to_parse = line;
657  bsl_mode = (flag >> 1) & 15;
658  if (prefix[0]) {
659  if (strncmp(line, prefix, strlen(prefix)) == 0) {
660  to_parse = line + strlen(prefix);
661  } else {
662  ret = 2; goto ex;
663  }
664  }
665  ret = Sfile_sep_make_argv(progname, to_parse, separators,
666  max_words, argc, argv,
667  (!(flag & 32)) | 4 | (bsl_mode << 5));
668  if (ret < 0) {
669  fprintf(stderr,
670  "%s : Severe lack of resources during command line parsing\n",
671  progname);
672  goto ex;
673  }
674  if (ret == 0) {
675  fprintf(stderr,
676  "%s : Incomplete quotation in %s line: %s\n",
677  progname, (flag & 32) ? "command" : "parsed", to_parse);
678  goto ex;
679  }
680 ex:;
681  if (ret <= 0)
682  Sfile_sep_make_argv("", "", "", 0, argc, argv, 2); /* release memory */
683  return(ret);
684 }
685 
686 
687 int dispose_parsed_words(int *argc, char ***argv)
688 {
689  Sfile_sep_make_argv("", "", "", 0, argc, argv, 2);
690  return(1);
691 }
692 
693 
694 /* -------------- Some helpers copied from xorriso/sfile.c ----------------- */
695 
696 
697 static int Sfile_destroy_argv(int *argc, char ***argv, int flag)
698 {
699  int i;
700 
701  if(*argc>0 && *argv!=NULL){
702  for(i=0;i<*argc;i++){
703  if((*argv)[i]!=NULL)
704  free((*argv)[i]);
705  }
706  free((char *) *argv);
707  }
708  *argc= 0;
709  *argv= NULL;
710  return(1);
711 }
712 
713 
714 /* Converts backslash codes into single characters:
715  \a BEL 7 , \b BS 8 , \e ESC 27 , \f FF 12 , \n LF 10 , \r CR 13 ,
716  \t HT 9 , \v VT 11 , \\ \ 92
717  \[0-9][0-9][0-9] octal code , \x[0-9a-f][0-9a-f] hex code ,
718  \cX control-x (ascii(X)-64)
719  @param upto maximum number of characters to examine for backslash.
720  The scope of a backslash (0 to 3 characters) is not affected.
721  @param eaten returns the difference in length between input and output
722  @param flag bit0= only determine *eaten, do not convert
723  bit1= convert \000 to binary 0
724 */
725 static int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag)
726 {
727  char *rpt, *wpt, num_text[8], wdummy[8];
728  unsigned int num= 0;
729 
730  *eaten= 0;
731  wpt= text;
732  for(rpt= text; *rpt != 0 && rpt - text < upto; rpt++) {
733  if(flag & 1)
734  wpt= wdummy;
735  if(*rpt == '\\') {
736  rpt++;
737  (*eaten)++;
738  if(*rpt == 'a') {
739  *(wpt++)= 7;
740  } else if(*rpt == 'b') {
741  *(wpt++)= 8;
742  } else if(*rpt == 'e') {
743  *(wpt++)= 27;
744  } else if(*rpt == 'f') {
745  *(wpt++)= 12;
746  } else if(*rpt == 'n') {
747  *(wpt++)= 10;
748  } else if(*rpt == 'r') {
749  *(wpt++)= 13;
750  } else if(*rpt == 't') {
751  *(wpt++)= 9;
752  } else if(*rpt == 'v') {
753  *(wpt++)= 11;
754  } else if(*rpt == '\\') {
755  *(wpt++)= '\\';
756  } else if(rpt[0] >= '0' && rpt[0] <= '7' &&
757  rpt[1] >= '0' && rpt[1] <= '7' &&
758  rpt[2] >= '0' && rpt[2] <= '7') {
759  num_text[0]= '0';
760  num_text[1]= *(rpt + 0);
761  num_text[2]= *(rpt + 1);
762  num_text[3]= *(rpt + 2);
763  num_text[4]= 0;
764  sscanf(num_text, "%o", &num);
765  if((num > 0 || (flag & 2)) && num <= 255) {
766  rpt+= 2;
767  (*eaten)+= 2;
768  *(wpt++)= num;
769  } else
770  goto not_a_code;
771  } else if(rpt[0] == 'x' &&
772  ((rpt[1] >= '0' && rpt[1] <= '9') ||
773  (rpt[1] >= 'A' && rpt[1] <= 'F') ||
774  (rpt[1] >= 'a' && rpt[1] <= 'f'))
775  &&
776  ((rpt[2] >= '0' && rpt[2] <= '9') ||
777  (rpt[2] >= 'A' && rpt[2] <= 'F') ||
778  (rpt[2] >= 'a' && rpt[2] <= 'f'))
779  ) {
780  num_text[0]= *(rpt + 1);
781  num_text[1]= *(rpt + 2);
782  num_text[2]= 0;
783  sscanf(num_text, "%x", &num);
784  if(num > 0 && num <= 255) {
785  rpt+= 2;
786  (*eaten)+= 2;
787  *(wpt++)= num;
788  } else
789  goto not_a_code;
790  } else if(*rpt == 'c') {
791  if(rpt[1] > 64 && rpt[1] < 96) {
792  *(wpt++)= rpt[1] - 64;
793  rpt++;
794  (*eaten)++;
795  } else
796  goto not_a_code;
797  } else {
798 not_a_code:;
799  *(wpt++)= '\\';
800  rpt--;
801  (*eaten)--;
802  }
803  } else
804  *(wpt++)= *rpt;
805  }
806  *wpt= *rpt;
807  return(1);
808 }
809 
810 
811 #define SfileadrL 4096
812 
813 static int Sfile_sep_make_argv(char *progname, char *line, char *separators,
814  int max_words, int *argc, char ***argv, int flag)
815 /*
816  bit0= read progname as first argument from line
817  bit1= just release argument list argv and return
818  bit2= abort with return(0) if incomplete quotes are found
819  bit3= eventually prepend missing '-' to first argument read from line
820  bit4= like bit2 but only check quote completeness, do not allocate memory
821  bit5+6= interpretation of backslashes:
822  0= no interpretation, leave unchanged
823  1= only inside double quotes
824  2= outside single quotes
825  3= everywhere
826  bit7= append a NULL element to argv
827 */
828 {
829  int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten;
830  char *cpt,*start;
831  char *buf= NULL;
832 
833  Sfile_destroy_argv(argc,argv,0);
834  if(flag&2)
835  {ret= 1; goto ex;}
836 
837  if(flag & 16)
838  flag|= 4;
839  bsl_mode= (flag >> 5) & 3;
840 
841  buf= calloc(strlen(line) + SfileadrL, 1);
842  if(buf == NULL)
843  {ret= -1; goto ex;}
844  for(pass=0;pass<2;pass++) {
845  cpt= line-1;
846  if(!(flag&1)){
847  argzaehl= line_start_argc= 1;
848  if(pass==0)
849  maxl= strlen(progname);
850  else
851  strcpy((*argv)[0],progname);
852  } else {
853  argzaehl= line_start_argc= 0;
854  if(pass==0) maxl= 0;
855  }
856  while(*(++cpt)!=0){
857  if(*separators) {
858  if(strchr(separators, *cpt) != NULL)
859  continue;
860  } else if(isspace(*cpt))
861  continue;
862  start= cpt;
863  buf[0]= 0;
864  cpt--;
865 
866  if(max_words > 0 && argzaehl >= max_words && *cpt != 0) {
867  /* take uninterpreted up to the end */
868  cpt+= strlen(cpt) - 1;
869  }
870 
871  while(*(++cpt)!=0) {
872  if(*separators) {
873  if(strchr(separators, *cpt) != NULL)
874  break;
875  } else if(isspace(*cpt))
876  break;
877  if(*cpt=='"'){
878  l= cpt-start; bufl= strlen(buf);
879  if(l>0) {
880  strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
881  if(bsl_mode >= 3) {
882  ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
883  if(ret <= 0)
884  goto ex;
885  }
886  }
887  l= strlen(buf);
888  start= cpt+1;
889  while(*(++cpt)!=0) if(*cpt=='"') break;
890  if((flag&4) && *cpt==0)
891  {ret= 0; goto ex;}
892  l= cpt-start; bufl= strlen(buf);
893  if(l>0) {
894  strncpy(buf + bufl, start, l);
895  buf[bufl + l]= 0;
896  if(bsl_mode >= 1) {
897  ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
898  if(ret <= 0)
899  goto ex;
900  }
901  }
902  start= cpt+1;
903  }else if(*cpt=='\''){
904  l= cpt-start; bufl= strlen(buf);
905  if(l>0) {
906  strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
907  if(bsl_mode >= 3) {
908  ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
909  if(ret <= 0)
910  goto ex;
911  }
912  }
913  l= strlen(buf);
914  start= cpt+1;
915  while(*(++cpt)!=0) if(*cpt=='\'') break;
916  if((flag&4) && *cpt==0)
917  {ret= 0; goto ex;}
918  l= cpt-start; bufl= strlen(buf);
919  if(l>0) {
920  strncat(buf,start,l);buf[bufl+l]= 0;
921  if(bsl_mode >= 2) {
922  ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
923  if(ret <= 0)
924  goto ex;
925  }
926  }
927  start= cpt+1;
928  }
929  if(*cpt==0) break;
930  }
931  l= cpt-start;
932  bufl= strlen(buf);
933  if(l>0) {
934  strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
935  if(bsl_mode >= 3) {
936  ret= Sfile_bsl_interpreter(buf, l, &eaten, 0);
937  if(ret <= 0)
938  goto ex;
939  }
940  }
941  l= strlen(buf);
942  if(pass==0){
943  if(argzaehl==line_start_argc && (flag&8))
944  if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
945  l++;
946  if(l>maxl) maxl= l;
947  }else{
948  strcpy((*argv)[argzaehl],buf);
949  if(argzaehl==line_start_argc && (flag&8))
950  if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
951  sprintf((*argv)[argzaehl],"-%s", buf);
952  }
953  argzaehl++;
954  if(*cpt==0) break;
955  }
956  if(pass==0){
957  if(flag & 16)
958  {ret= 1; goto ex;}
959  *argc= argzaehl;
960  if(argzaehl>0 || (flag & 128)) {
961  *argv= (char **) calloc((argzaehl + !!(flag & 128)), sizeof(char *));
962  if(*argv==NULL)
963  {ret= -1; goto ex;}
964  }
965  for(i=0;i<*argc;i++) {
966  (*argv)[i]= (char *) calloc(maxl + 1, 1);
967  if((*argv)[i]==NULL)
968  {ret= -1; goto ex;}
969  }
970  if(flag & 128)
971  (*argv)[*argc]= NULL;
972  }
973  }
974  ret= 1;
975 ex:
976  if(buf != NULL)
977  free(buf);
978  return(ret);
979 }
980 
int main(int argc, char *argv[])
static int Sfile_sep_make_argv(char *progname, char *line, char *separators, int max_words, int *argc, char ***argv, int flag)
static int await_all_replies(struct boss_state *boss)
#define Frontend_xorriso_max_resulT
static int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag)
static int record_reply_line(struct boss_state *boss, char *line)
static int prompt_for_command(struct boss_state *boss, char *line, int line_size)
static int show_parsed(struct boss_state *boss, char *line)
static int input_interpreter(char *line, struct boss_state *boss)
int dispose_parsed_words(int *argc, char ***argv)
static int Sfile_destroy_argv(int *argc, char ***argv, int flag)
static int transmit_command(struct boss_state *boss, char *line)
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)
static int usage()
static int de_pkt_result(struct boss_state *boss)
static int make_reply_lines(struct boss_state *boss)
#define SfileadrL