"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(&current_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