"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/frontend/frontend_pipes_xorriso.c" (30 Jan 2021, 28855 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "frontend_pipes_xorriso.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.5.2_vs_1.5.4.
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 */
68 int command_fd;
69 int reply_fd;
70
71 /* For synchronization between boss and xorriso */
72 int mark_count;
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;
86 int reply_lines_count;
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;
445 boss->reply_lines_size = Frontend_xorriso_max_resulT;
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;
466 boss->reply_lines_size = Frontend_xorriso_max_resulT;
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
575 boss->reply_lines = calloc(Frontend_xorriso_max_resulT,
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