"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/xorriso/sfile.c" (30 Jan 2021, 23156 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 "sfile.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 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
3
4 Copyright 2007-2020 Thomas Schmitt, <scdbackup@gmx.net>
5
6 Provided under GPL version 2 or later.
7
8 This file contains the implementation of functions around files and strings.
9 */
10
11 #ifdef HAVE_CONFIG_H
12 #include "../config.h"
13 #endif
14
15 #include <ctype.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <time.h>
24 #include <pwd.h>
25 #include <grp.h>
26
27
28 #include "sfile.h"
29
30
31 /* @param flag bit0= do not clip off carriage return at line end
32 */
33 char *Sfile_fgets_n(char *line, int maxl, FILE *fp, int flag)
34 {
35 int l;
36 char *ret;
37
38 ret= fgets(line,maxl,fp);
39 if(ret==NULL)
40 return(NULL);
41 l= strlen(line);
42 if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0;
43 if(l > 0) if(line[l-1] == '\n') line[--l]= 0;
44 if(l > 0 && !(flag & 1)) if(line[l-1] == '\r') line[--l]= 0;
45 return(ret);
46 }
47
48
49 int Sfile_count_char(char *text, char to_count)
50 {
51 int count= 0;
52 char *cpt;
53
54 for(cpt= text; *cpt != 0; cpt++)
55 if(*cpt == to_count)
56 count++;
57 return count;
58 }
59
60
61 int Sfile_count_components(char *path, int flag)
62 /*
63 bit0= do not ignore trailing slash
64 bit1= do not ignore empty components (other than the empty root name)
65 */
66 {
67 int l,count= 0;
68 char *cpt;
69
70 l= strlen(path);
71 if(l==0)
72 return(0);
73 count= 1;
74 for(cpt= path+l-1;cpt>=path;cpt--) {
75 if(*cpt=='/') {
76 if(*(cpt+1)==0 && !(flag&1))
77 continue;
78 if(*(cpt+1)=='/' && !(flag&2))
79 continue;
80 count++;
81 }
82 }
83 return(count);
84 }
85
86
87 int Sfile_component_pointer(char *path, char **sourcept, int idx, int flag)
88 /*
89 bit0= do not ignore trailing slash
90 bit1= do not ignore empty components (other than the empty root name)
91 bit2= accept 0 as '/'
92 */
93 {
94 int count= 0;
95 char *spt;
96
97 for(spt= path;*spt!=0 || (flag&4);spt++) {
98 if(count>=idx) {
99 *sourcept= spt;
100 return(1);
101 }
102 if(*spt=='/' || *spt==0) {
103 if(*(spt+1)=='/' && !(flag&2))
104 continue;
105 if(*(spt+1)==0 && !(flag&1))
106 continue;
107 count++;
108 }
109 }
110 if((flag&1) && count>=idx)
111 return(1);
112 return(0);
113 }
114
115
116 int Sfile_leafname(char *path, char leafname[SfileadrL], int flag)
117 {
118 int count, ret;
119 char *lpt;
120
121 leafname[0]= 0;
122 count= Sfile_count_components(path, 0);
123 if(count==0)
124 return(0);
125 ret= Sfile_component_pointer(path, &lpt, count-1, 0);
126 if(ret<=0)
127 return(ret);
128 if(Sfile_str(leafname, lpt, 0)<=0)
129 return(0);
130 lpt= strchr(leafname, '/');
131 if(lpt!=NULL)
132 *lpt= 0;
133 return(1);
134 }
135
136
137 int Sfile_add_to_path(char path[SfileadrL], char *addon, int flag)
138 {
139 int l;
140
141 l= strlen(path);
142 if(l+1>=SfileadrL)
143 return(0);
144 if(l==0) {
145 strcpy(path,"/");
146 l= 1;
147 } else if(path[l-1]!='/') {
148 path[l++]= '/';
149 path[l]= 0;
150 }
151 if(l+strlen(addon)>=SfileadrL)
152 return(0);
153 if(addon[0]=='/')
154 strcpy(path+l,addon+1);
155 else
156 strcpy(path+l,addon);
157 return(1);
158 }
159
160
161 int Sfile_prepend_path(char *prefix, char path[SfileadrL], int flag)
162 {
163 int l, i, slashes, prefix_len, path_len;
164
165 l= strlen(prefix);
166 if(l == 0)
167 return(1);
168
169 /* Do not copy slashes between both parts */
170 for(prefix_len= l; prefix_len > 0; prefix_len--)
171 if(prefix[prefix_len - 1] != '/')
172 break;
173 if(prefix_len == 0)
174 prefix_len= strlen(prefix) - 1;
175 path_len= strlen(path);
176 for(slashes= 0; slashes < path_len; slashes++)
177 if(path[slashes] != '/')
178 break;
179
180 l= (strlen(path) - slashes) + prefix_len + 1;
181 if(l>=SfileadrL) {
182
183 #ifdef Not_yeT
184 /* >>> ??? how to transport messages to xorriso ? */
185 sprintf(xorriso->info_text,
186 "Combination of wd and relative address too long (%d > %d)",
187 l,SfileadrL-1);
188 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
189 #endif
190
191 return(-1);
192 }
193 l-= strlen(path);
194 if(l < 0) {
195 for(i= slashes; i <= path_len + 1; i++)
196 path[i+l]= path[i];
197 } else if(l > 0) {
198 for(i= path_len + 1; i >= slashes; i--)
199 path[i+l]= path[i];
200 }
201 if(prefix_len > 0)
202 memcpy(path, prefix, prefix_len);
203 path[l - 1 + slashes]= '/';
204 return(1);
205 }
206
207
208 int Sfile_get_dev_fd_no(char *filename, int flag)
209 {
210 int i, fd= -1;
211
212 if(strncmp(filename, "/dev/fd/", 8) != 0)
213 return(-1);
214 for(i = 8; filename[i]; i++)
215 if(filename[i] < '0' || filename[i] > '9')
216 break;
217 if(i > 8 && filename[i] == 0)
218 sscanf(filename + 8, "%d", &fd);
219 if(fd < 0)
220 fd = -1;
221 return(fd);
222 }
223
224
225 int Sfile_type(char *filename, int flag)
226 /*
227 bit0= return -1 if file is missing
228 bit1= return a hardlink with siblings as type 5
229 bit2= evaluate eventual link target rather than the link object itself
230 bit3= return a socket or a char device as types 7 or 8 rather than 0
231 bit4= interpret /dev/fd/#fd# as open file descriptor fd
232 */
233 /*
234 return:
235 0=unknown
236 1=regular
237 2=directory
238 3=symbolic link
239 4=named pipe
240 5=multiple hardlink (with bit1)
241 6=block device
242 7=socket (with bit3)
243 8=character device (with bit3)
244 | 1024 if interpreted as /dev/fd/#fd#
245 | 2048 if interpreted as /dev/fd/#fd# and not fstatable
246 */
247 {
248 struct stat stbuf;
249 int fd= -1, was_dev_fd= 0, ret;
250
251 if(flag & 16)
252 fd= Sfile_get_dev_fd_no(filename, 0);
253 if(fd != -1) {
254 was_dev_fd= 1;
255 if(fstat(fd, &stbuf) == -1)
256 return(1024 | 2048);
257 } else if(flag&4) {
258 if(stat(filename,&stbuf)==-1) {
259 if(flag&1) return(-1);
260 else return(0);
261 }
262 } else {
263 if(lstat(filename,&stbuf)==-1) {
264 if(flag&1) return(-1);
265 else return(0);
266 }
267 }
268 if(S_ISREG(stbuf.st_mode)) {
269 if(flag&2)
270 if(stbuf.st_nlink>1)
271 {ret= 5; goto ex;}
272 {ret= 1; goto ex;}
273 }
274 if(S_ISDIR(stbuf.st_mode))
275 {ret= 2; goto ex;}
276 if((stbuf.st_mode&S_IFMT)==S_IFLNK)
277 {ret= 3; goto ex;}
278 if(S_ISFIFO(stbuf.st_mode))
279 {ret= 4; goto ex;}
280 if(S_ISBLK(stbuf.st_mode))
281 {ret= 6; goto ex;}
282 if(flag&8)
283 if((stbuf.st_mode&S_IFMT)==S_IFSOCK)
284 {ret= 7; goto ex;}
285 if(flag&8)
286 if(S_ISCHR(stbuf.st_mode))
287 {ret= 8; goto ex;}
288 ret = 0;
289 ex:;
290 return(ret | (was_dev_fd << 10));
291 }
292
293
294 char *Sfile_datestr(time_t tim, short int flag)
295 /*
296 bit0=with hours+minutes
297 bit1=with seconds
298
299 bit8= local time rather than UTC
300 */
301 {
302 static char zeitcode[80]={"000000"};
303 char puff[80];
304 struct tm *azt;
305
306 if(flag&256)
307 azt = localtime(&tim);
308 else
309 azt = gmtime(&tim);
310
311 if(azt->tm_year>99)
312 sprintf(zeitcode,"%c%1.1d%2.2d%2.2d",
313 'A'+(azt->tm_year-100)/10,azt->tm_year%10,
314 azt->tm_mon+1,azt->tm_mday);
315 else
316 sprintf(zeitcode,"%2.2d%2.2d%2.2d",
317 azt->tm_year,azt->tm_mon+1,azt->tm_mday);
318 if(flag&1){
319 sprintf(puff,".%2.2d%2.2d",azt->tm_hour,azt->tm_min);
320 strcat(zeitcode,puff);
321 }
322 if(flag&2){
323 sprintf(puff,"%2.2d",azt->tm_sec);
324 strcat(zeitcode,puff);
325 }
326
327 return(zeitcode);
328 }
329
330
331 int Sfile_scale(double value, char *result, int siz, double thresh, int flag)
332 /*
333 bit0= omit 'b' if it would elsewise be appended
334 bit1= make text as short as possible
335 bit2= no fraction (if it would fit at all)
336 */
337 {
338 char scale_c,scales[7],form[80], *negpt= NULL, *cpt;
339 int i,dec_siz= 0,avail_siz= 1;
340
341 if(value<0) {
342 value= -value;
343 siz--;
344 result[0]= '-';
345 negpt= result;
346 result++;
347 }
348 strcpy(scales,"bkmgtp");
349 scale_c= scales[0];
350 for(i=1;scales[i]!=0;i++) {
351 if(value<thresh-0.5)
352 break;
353 value/= 1024.0;
354 scale_c= scales[i];
355 }
356 if(scale_c!='b' && !(flag&4)) { /* is there room for fractional part ? */
357 avail_siz= siz-1;
358 sprintf(form,"%%.f");
359 sprintf(result,"%.f",value);
360 if(((int) strlen(result)) <= avail_siz - 2)
361 dec_siz= 1; /* we are very modest */
362 }
363 if(scale_c=='b' && (flag&1)) {
364 if(flag&2)
365 sprintf(form,"%%.f");
366 else
367 sprintf(form,"%%%d.f",siz);
368 sprintf(result,form,value);
369 } else {
370 if(flag&2)
371 sprintf(form,"%%.f%%c");
372 else if(dec_siz>0)
373 sprintf(form,"%%%d.%df%%c",avail_siz,dec_siz);
374 else
375 sprintf(form,"%%%d.f%%c",siz-1);
376 sprintf(result,form,value,scale_c);
377 }
378 if(negpt != NULL) {
379 for(cpt= result; *cpt==' '; cpt++);
380 if(cpt > result) {
381 *negpt= ' ';
382 *(cpt - 1)= '-';
383 }
384 }
385 return(1);
386 }
387
388
389 int Sfile_off_t_text(char text[80], off_t num, int flag)
390 {
391 char *tpt;
392 off_t hnum, scale= 1;
393 int digits= 0, d, i;
394
395 tpt= text;
396 hnum= num;
397 if(hnum<0) {
398 *(tpt++)= '-';
399 hnum= -num;
400 }
401 if(hnum<0) { /* it can stay nastily persistent */
402 strcpy(text, "_overflow_");
403 return(0);
404 }
405 for(i= 0; i<23; i++) { /* good for up to 70 bit = 10 exp 21.07... */
406 if(hnum==0)
407 break;
408 hnum/= 10;
409 if(hnum)
410 scale*= 10;
411 }
412 if(i==0) {
413 strcpy(text, "0");
414 return(1);
415 }
416 if(i==23) {
417 strcpy(text, "_overflow_");
418 return(0);
419 }
420 digits= i;
421 hnum= num;
422 for(; i>0; i--) {
423 d= hnum/scale;
424 tpt[digits-i]= '0'+d;
425 hnum= hnum%scale;
426 scale/= 10;
427 }
428 tpt[digits]= 0;
429 return(1);
430 }
431
432
433 /* @return index number of first not interpreted text byte
434 */
435 int Sfile_text_to_off_t(char *text, off_t *num, int flag)
436 {
437 int sig= 1, ridx;
438
439 *num= 0;
440 ridx= 0;
441 if(text[ridx] == '-') {
442 sig= -1;
443 ridx++;
444 } else if(text[ridx] == '+') {
445 ridx++;
446 }
447 for(; text[ridx] != 0; ridx++) {
448 if(text[ridx] < '0' || text[ridx] > '9')
449 break;
450 if(*num > (((off_t) 1) << 59))
451 return(-1);
452 *num= *num * 10 + text[ridx] - '0';
453 }
454 *num= *num * sig;
455 return(ridx);
456 }
457
458
459 /* Converts backslash codes into single characters:
460 \a BEL 7 , \b BS 8 , \e ESC 27 , \f FF 12 , \n LF 10 , \r CR 13 ,
461 \t HT 9 , \v VT 11 , \\ \ 92
462 \[0-9][0-9][0-9] octal code , \x[0-9a-f][0-9a-f] hex code ,
463 \cX control-x (ascii(X)-64)
464 @param upto maximum number of characters to examine for backslash.
465 The scope of a backslash (0 to 3 characters) is not affected.
466 @param eaten returns the difference in length between input and output
467 @param flag bit0= only determine *eaten, do not convert
468 bit1= convert \000 to binary 0
469 */
470 int Sfile_bsl_interpreter(char *text, int upto, int *eaten, int flag)
471 {
472 char *rpt, *wpt, num_text[8], wdummy[8];
473 unsigned int num= 0;
474
475 *eaten= 0;
476 wpt= text;
477 for(rpt= text; *rpt != 0 && rpt - text < upto; rpt++) {
478 if(flag & 1)
479 wpt= wdummy;
480 if(*rpt == '\\') {
481 rpt++;
482 (*eaten)++;
483 if(*rpt == 'a') {
484 *(wpt++)= 7;
485 } else if(*rpt == 'b') {
486 *(wpt++)= 8;
487 } else if(*rpt == 'e') {
488 *(wpt++)= 27;
489 } else if(*rpt == 'f') {
490 *(wpt++)= 12;
491 } else if(*rpt == 'n') {
492 *(wpt++)= 10;
493 } else if(*rpt == 'r') {
494 *(wpt++)= 13;
495 } else if(*rpt == 't') {
496 *(wpt++)= 9;
497 } else if(*rpt == 'v') {
498 *(wpt++)= 11;
499 } else if(*rpt == '\\') {
500 *(wpt++)= '\\';
501 } else if(rpt[0] >= '0' && rpt[0] <= '7' &&
502 rpt[1] >= '0' && rpt[1] <= '7' &&
503 rpt[2] >= '0' && rpt[2] <= '7') {
504 num_text[0]= '0';
505 num_text[1]= *(rpt + 0);
506 num_text[2]= *(rpt + 1);
507 num_text[3]= *(rpt + 2);
508 num_text[4]= 0;
509 sscanf(num_text, "%o", &num);
510 if((num > 0 || (flag & 2)) && num <= 255) {
511 rpt+= 2;
512 (*eaten)+= 2;
513 *(wpt++)= num;
514 } else
515 goto not_a_code;
516 } else if(rpt[0] == 'x' &&
517 ((rpt[1] >= '0' && rpt[1] <= '9') ||
518 (rpt[1] >= 'A' && rpt[1] <= 'F') ||
519 (rpt[1] >= 'a' && rpt[1] <= 'f'))
520 &&
521 ((rpt[2] >= '0' && rpt[2] <= '9') ||
522 (rpt[2] >= 'A' && rpt[2] <= 'F') ||
523 (rpt[2] >= 'a' && rpt[2] <= 'f'))
524 ) {
525 num_text[0]= *(rpt + 1);
526 num_text[1]= *(rpt + 2);
527 num_text[2]= 0;
528 sscanf(num_text, "%x", &num);
529 if(num > 0 && num <= 255) {
530 rpt+= 2;
531 (*eaten)+= 2;
532 *(wpt++)= num;
533 } else
534 goto not_a_code;
535 } else if(*rpt == 'c') {
536 if(rpt[1] > 64 && rpt[1] < 96) {
537 *(wpt++)= rpt[1] - 64;
538 rpt++;
539 (*eaten)++;
540 } else
541 goto not_a_code;
542 } else {
543 not_a_code:;
544 *(wpt++)= '\\';
545 rpt--;
546 (*eaten)--;
547 }
548 } else
549 *(wpt++)= *rpt;
550 }
551 *wpt= *rpt;
552 return(1);
553 }
554
555
556 /* @param flag bit0= only encode inside quotes
557 bit1= encode < 32 outside quotes except 7, 8, 9, 10, 12, 13
558 bit2= encode in any case above 126
559 bit3= encode in any case shellsafe and name-value-safe:
560 <=42 , 59, 60, 61, 62, 63, 92, 94, 96, >=123
561 */
562 int Sfile_bsl_encoder(char **result, char *text, size_t text_len, int flag)
563 {
564 signed char *rpt;
565 char *wpt;
566 int count, sq_open= 0, dq_open= 0;
567
568 count= 0;
569 for(rpt= (signed char *) text; (size_t) (((char *) rpt) - text) < text_len;
570 rpt++) {
571 count++;
572 if(flag & 8) {
573 if(!(*rpt <= 42 || (*rpt >= 59 && *rpt <= 63) ||
574 *rpt == 92 || *rpt == 94 || *rpt == 96 || *rpt >= 123))
575 continue;
576 } else if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\')
577 continue;
578 if(((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') && !(flag & 8))
579 count++;
580 else
581 count+= 3;
582 }
583 (*result)= wpt= calloc(count + 1, 1);
584 if(wpt == NULL)
585 return(-1);
586 for(rpt= (signed char *) text; (size_t) (((char *) rpt) - text) < text_len;
587 rpt++) {
588 if(*rpt == '\'')
589 sq_open= !(sq_open || dq_open);
590 if(*rpt == '"')
591 dq_open= !(sq_open || dq_open);
592
593 if(flag & 8) {
594 if(!(*rpt <= 42 || (*rpt >= 59 && *rpt <= 63) ||
595 *rpt == 92 || *rpt == 94 || *rpt == 96 || *rpt >= 123)) {
596 *(wpt++)= *rpt;
597 continue;
598 }
599 } else if(*rpt >= 32 && *rpt <= 126 && *rpt != '\\') {
600 *(wpt++)= *rpt;
601 continue;
602 } else if( ((flag & 1) && !(sq_open || dq_open)) &&
603 !((flag & 2) && (*rpt >= 1 && * rpt <= 31 &&
604 !(*rpt == 7 || *rpt == 8 || *rpt == 9 || *rpt == 10 ||
605 *rpt == 12 || *rpt == 13))) &&
606 !((flag & 4) && (*rpt > 126 || *rpt < 0)) &&
607 !((flag & 6) && *rpt == '\\')) {
608 *(wpt++)= *rpt;
609 continue;
610 }
611 *(wpt++)= '\\';
612 if(((*rpt >= 7 && *rpt <= 13) || *rpt == 27 || *rpt == '\\') && !(flag&8)) {
613 if(*rpt == 7)
614 *(wpt++)= 'a';
615 else if(*rpt == 8)
616 *(wpt++)= 'b';
617 else if(*rpt == 9)
618 *(wpt++)= 't';
619 else if(*rpt == 10) {
620 *(wpt++)= 'n';
621 } else if(*rpt == 11)
622 *(wpt++)= 'v';
623 else if(*rpt == 12)
624 *(wpt++)= 'f';
625 else if(*rpt == 13)
626 *(wpt++)= 'r';
627 else if(*rpt == 27)
628 *(wpt++)= 'e';
629 else if(*rpt == '\\')
630 *(wpt++)= '\\';
631 } else {
632 sprintf(wpt, "%-3.3o", (unsigned int) *((unsigned char *) rpt));
633 wpt+= 3;
634 }
635 }
636 *wpt= 0;
637 return(1);
638 }
639
640
641 int Sfile_destroy_argv(int *argc, char ***argv, int flag)
642 {
643 int i;
644
645 if(*argc>0 && *argv!=NULL){
646 for(i=0;i<*argc;i++){
647 if((*argv)[i]!=NULL)
648 Smem_freE((*argv)[i]);
649 }
650 Smem_freE((char *) *argv);
651 }
652 *argc= 0;
653 *argv= NULL;
654 return(1);
655 }
656
657
658 int Sfile_sep_make_argv(char *progname, char *line, char *separators,
659 int max_words, int *argc, char ***argv, int flag)
660 /*
661 bit0= read progname as first argument from line
662 bit1= just release argument list argv and return
663 bit2= abort with return(0) if incomplete quotes are found
664 bit3= eventually prepend missing '-' to first argument read from line
665 bit4= like bit2 but only check quote completeness, do not allocate memory
666 bit5+6= interpretation of backslashes:
667 0= no interpretation, leave unchanged
668 1= only inside double quotes
669 2= outside single quotes
670 3= everywhere
671 bit7= append a NULL element to argv
672 */
673 {
674 int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten;
675 char *cpt,*start;
676 char *buf= NULL;
677
678 Sfile_destroy_argv(argc,argv,0);
679 if(flag&2)
680 {ret= 1; goto ex;}
681
682 if(flag & 16)
683 flag|= 4;
684 bsl_mode= (flag >> 5) & 3;
685
686 buf= calloc(strlen(line) + SfileadrL, 1);
687 if(buf == NULL)
688 {ret= -1; goto ex;}
689 for(pass=0;pass<2;pass++) {
690 cpt= line-1;
691 if(!(flag&1)){
692 argzaehl= line_start_argc= 1;
693 if(pass==0)
694 maxl= strlen(progname);
695 else
696 strcpy((*argv)[0],progname);
697 } else {
698 argzaehl= line_start_argc= 0;
699 if(pass==0) maxl= 0;
700 }
701 while(*(++cpt)!=0){
702 if(*separators) {
703 if(strchr(separators, *cpt) != NULL)
704 continue;
705 } else if(isspace(*cpt))
706 continue;
707 start= cpt;
708 buf[0]= 0;
709 cpt--;
710
711 if(max_words > 0 && argzaehl >= max_words && *cpt != 0) {
712 /* take uninterpreted up to the end */
713 cpt+= strlen(cpt) - 1;
714 }
715
716 while(*(++cpt)!=0) {
717 if(*separators) {
718 if(strchr(separators, *cpt) != NULL)
719 break;
720 } else if(isspace(*cpt))
721 break;
722 if(*cpt=='"'){
723 l= cpt-start; bufl= strlen(buf);
724 if(l>0) {
725 strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
726 if(bsl_mode >= 3) {
727 ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
728 if(ret <= 0)
729 goto ex;
730 }
731 }
732 l= strlen(buf);
733 start= cpt+1;
734 while(*(++cpt)!=0) if(*cpt=='"') break;
735 if((flag&4) && *cpt==0)
736 {ret= 0; goto ex;}
737 l= cpt-start; bufl= strlen(buf);
738 if(l>0) {
739 strncpy(buf + bufl, start, l);
740 buf[bufl + l]= 0;
741 if(bsl_mode >= 1) {
742 ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
743 if(ret <= 0)
744 goto ex;
745 }
746 }
747 start= cpt+1;
748 }else if(*cpt=='\''){
749 l= cpt-start; bufl= strlen(buf);
750 if(l>0) {
751 strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
752 if(bsl_mode >= 3) {
753 ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
754 if(ret <= 0)
755 goto ex;
756 }
757 }
758 l= strlen(buf);
759 start= cpt+1;
760 while(*(++cpt)!=0) if(*cpt=='\'') break;
761 if((flag&4) && *cpt==0)
762 {ret= 0; goto ex;}
763 l= cpt-start; bufl= strlen(buf);
764 if(l>0) {
765 strncat(buf,start,l);buf[bufl+l]= 0;
766 if(bsl_mode >= 2) {
767 ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
768 if(ret <= 0)
769 goto ex;
770 }
771 }
772 start= cpt+1;
773 }
774 if(*cpt==0) break;
775 }
776 l= cpt-start;
777 bufl= strlen(buf);
778 if(l>0) {
779 strncpy(buf + bufl, start, l); buf[bufl + l]= 0;
780 if(bsl_mode >= 3) {
781 ret= Sfile_bsl_interpreter(buf + bufl, l, &eaten, 0);
782 if(ret <= 0)
783 goto ex;
784 }
785 }
786 l= strlen(buf);
787 if(pass==0){
788 if(argzaehl==line_start_argc && (flag&8))
789 if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
790 l++;
791 if(l>maxl) maxl= l;
792 }else{
793 strcpy((*argv)[argzaehl],buf);
794 if(argzaehl==line_start_argc && (flag&8))
795 if(buf[0]!='-' && buf[0]!=0 && buf[0]!='#')
796 sprintf((*argv)[argzaehl],"-%s", buf);
797 }
798 argzaehl++;
799 if(*cpt==0) break;
800 }
801 if(pass==0){
802 if(flag & 16)
803 {ret= 1; goto ex;}
804 *argc= argzaehl;
805 if(argzaehl>0 || (flag & 128)) {
806 *argv= (char **) Smem_malloC((argzaehl + !!(flag & 128))
807 * sizeof(char *));
808 if(*argv==NULL)
809 {ret= -1; goto ex;}
810 }
811 for(i=0;i<*argc;i++) {
812 (*argv)[i]= (char *) Smem_malloC((maxl+1));
813 if((*argv)[i]==NULL)
814 {ret= -1; goto ex;}
815 }
816 if(flag & 128)
817 (*argv)[*argc]= NULL;
818 }
819 }
820 ret= 1;
821 ex:
822 if(buf != NULL)
823 free(buf);
824 return(ret);
825 }
826
827
828 int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv,
829 int flag)
830 {
831 return Sfile_sep_make_argv(progname, line, "", 0, argc, argv, flag);
832 }
833
834
835 /* @param flag bit0= append */
836 int Sfile_str(char target[SfileadrL], char *source, int flag)
837 {
838 int l;
839
840 l= strlen(source);
841 if(flag&1)
842 l+= strlen(target);
843 if(l>=SfileadrL) {
844 fprintf(stderr, "--- Path string overflow (%d > %d). Malicious input ?\n",
845 l,SfileadrL-1);
846 return(0);
847 }
848 if(flag&1)
849 strcat(target, source);
850 else
851 strcpy(target, source);
852 return(1);
853 }
854
855
856 /** Combine environment variable HOME with given filename
857 @param filename Address relative to $HOME
858 @param fileadr Resulting combined address
859 @param fa_size Size of array fileadr
860 @param flag Unused yet
861 @return 1=ok , 0=no HOME variable , -1=result address too long
862 */
863 int Sfile_home_adr_s(char *filename, char *fileadr, int fa_size, int flag)
864 {
865 char *home;
866
867 strcpy(fileadr,filename);
868 home= getenv("HOME");
869 if(home==NULL)
870 return(0);
871 if((int) (strlen(home) + strlen(filename) + 1) >= fa_size)
872 return(-1);
873 strcpy(fileadr,home);
874 if(filename[0]!=0){
875 strcat(fileadr,"/");
876 strcat(fileadr,filename);
877 }
878 return(1);
879 }
880
881
882 /** Return a double representing seconds and microseconds since 1 Jan 1970 */
883 double Sfile_microtime(int flag)
884 {
885 struct timeval tv;
886
887 gettimeofday(&tv, NULL);
888 return((double) (tv.tv_sec+1.0e-6*tv.tv_usec));
889 }
890
891
892 int Sfile_decode_datestr(struct tm *reply, char *text, int flag)
893 /* YYMMDD[.hhmm[ss]] */
894 {
895 int i,l;
896 time_t current_time;
897 struct tm *now;
898
899 current_time= time(0);
900 now= localtime(¤t_time);
901 for(i=0; i < (int) sizeof(struct tm); i++)
902 ((char *) reply)[i]= ((char *) now)[i];
903
904 if(text[0]<'0'|| (text[0]>'9' && text[0]<'A') || text[0]>'Z')
905 return(0);
906 l= strlen(text);
907 for(i=1;i<l;i++)
908 if(text[i]<'0'||text[i]>'9')
909 break;
910 if(i!=6)
911 return(0);
912 if(text[i]==0)
913 goto decode;
914 if(text[i]!='.' || (l!=11 && l!=13))
915 return(0);
916 for(i++;i<l;i++)
917 if(text[i]<'0'||text[i]>'9')
918 break;
919 if(i!=l)
920 return(0);
921
922 decode:;
923 reply->tm_hour= 0;
924 reply->tm_min= 0;
925 reply->tm_sec= 0;
926 i= 0;
927 if(text[0]>='A')
928 reply->tm_year= 100+(text[i]-'A')*10+text[1]-'0';
929 else
930 reply->tm_year= 10*(text[0]-'0')+text[1]-'0';
931 reply->tm_mon= 10*(text[2]-'0')+text[3]-'0'-1;
932 reply->tm_mday= 10*(text[4]-'0')+text[5]-'0';
933 if(l==6)
934 return(1);
935 reply->tm_hour= 10*(text[7]-'0')+text[8]-'0';
936 reply->tm_min= 10*(text[9]-'0')+text[10]-'0';
937 if(l==11)
938 return(1);
939 reply->tm_sec= 10*(text[11]-'0')+text[12]-'0';
940 return(1);
941 }
942
943
944 /* From libisofs:
945 Find backward from idx the start byte of a possible UTF-8 character.
946 https://en.wikipedia.org/wiki/UTF-8#Description
947 */
948 static
949 int find_utf8_start(char *name, int idx, int flag)
950 {
951 unsigned char *uname, uch;
952 int i;
953
954 uname= (unsigned char *) name;
955 if ((uname[idx] & 0xc0) != 0x80)
956 return idx; /* not an UTF-8 tail byte */
957 for (i = 0; i < 5 && idx - 1 - i >= 0; i++) {
958 /* up to deprecated 6-byte codes */
959 uch = uname[idx - 1 - i];
960 if ((uch & 0xe0) == 0xc0 || (uch & 0xf0) == 0xe0 ||
961 (uch & 0xf8) == 0xf0 || (uch & 0xfc) == 0xf8 ||
962 (uch & 0xfe) == 0xfc)
963 return (idx - 1 - i); /* UTF-8 start byte found */
964 if ((uch & 0xc0) != 0x80)
965 return idx; /* not an UTF-8 tail byte, so no UTF-8 */
966 }
967 return idx; /* no UTF-8 start found */
968 }
969
970
971 int Sfile_flatten_utf8_heads(char *name, int idx, int flag)
972 {
973 int neck;
974
975 neck = find_utf8_start(name, idx, 0);
976 if(neck >= idx)
977 return(2);
978 for(; neck < idx; neck++)
979 name[neck] = '_';
980 return(1);
981 }
982
983