home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / dirfold / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  17.7 KB  |  756 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <limits.h>
  6. #ifndef NO_GETOPT_H
  7. #  include <getopt.h>
  8. #endif
  9. #include <errno.h>
  10. #include <dirent.h>
  11. #include <signal.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <pwd.h>
  17. #include <time.h>
  18.  
  19. #define BIND_CONST
  20. #include <h/keys.h>
  21. #include <h/envvar_str.h>
  22. #include <h/os.h>
  23.  
  24. #include <lib/ori_add_lib.h>
  25. #include <lib/ori_rc_lib.h>
  26. #include <lib/ori_re_lib.h>
  27. #include <h/rcformat.h>
  28. /*}}}  */
  29.  
  30. /*{{{  variables*/
  31. #define START_DEPTH 255
  32. /*{{{  fold-marks*/
  33. char fold_open_str[FOLD_TAG_LENGTH+1]=BEGIN_STANDARD;
  34. char fold_close_str[FOLD_TAG_LENGTH+1]=END_STANDARD;
  35. char fold_file_str[FOLD_TAG_LENGTH+1]=FILE_STANDARD;
  36. char fold_line_str[FOLD_TAG_LENGTH+1]=LINE_STANDARD;
  37. /*}}}  */
  38. /*{{{  for commandline-options*/
  39. char const *keybase=0;
  40. char const *ori_path=ORIGAMI_RC_PATH;
  41. int always=0;
  42. int mark_no_perm=0;
  43. #ifdef REGEXP
  44.    char const *match_str="";
  45.    regex_t preg_match;
  46.    char const *no_match_str="";
  47.    regex_t preg_no_match;
  48.    int aborted=0;
  49.    regmatch_t ma[1];
  50. #endif
  51. /*}}}  */
  52. int single=0;
  53. int depth=START_DEPTH;
  54. uid_t user;
  55. gid_t group;
  56. int long_format=0;
  57. /*}}}  */
  58.  
  59. /*{{{  error_exit*/
  60. void error_exit(char const * const m)
  61.  {
  62.    fputs(m,stderr);
  63.    exit(1);
  64.  }
  65. /*}}}  */
  66. /*{{{  set_other_mark*/
  67. /*{{{  parse rcfile*/
  68. int rc_file_parser(char const * const mark_mode,FILE * const rcfile)
  69. {
  70.   readtags input;
  71.  
  72.   rc_get_w(rcfile);
  73.   while ((input=rc_get_c(rcfile))!=RC_ENDE && input!=RC_BIND)
  74.    { switch (input) {
  75.        /*{{{  termalias*/
  76.        case RC_TERMALIAS:
  77.         { int ch;
  78.  
  79.           while ((ch=rc_get_c(rcfile)) && ch!=EOF)
  80.              do ch=rc_get_c(rcfile); while (ch && ch!=EOF);
  81.           do ch=rc_get_c(rcfile); while (ch && ch!=EOF);
  82.           continue;
  83.         }
  84.        /*}}}  */
  85.        /*{{{  usermodestrings*/
  86.        case RC_MODE: {
  87.          int lg;
  88.  
  89.          rc_get_c(rcfile);
  90.          lg=rc_get_w(rcfile);
  91.          if (lg)
  92.             rc_skip_cw(rcfile,lg,0);
  93.          lg=rc_get_w(rcfile);
  94.          if (lg)
  95.             rc_skip_cw(rcfile,lg,0);
  96.          continue;
  97.        }
  98.        /*}}}  */
  99.        /*{{{  macroload/init*/
  100.        case RC_LOADMACRO:
  101.        case RC_INITMACRO:
  102.         { int lg;
  103.  
  104.           rc_get_w(rcfile);
  105.           lg=rc_get_w(rcfile);
  106.           rc_skip_cw(rcfile,0,lg);
  107.           continue;
  108.         }
  109.        /*}}}  */
  110.        /*{{{  consts*/
  111.        case RC_CONST:
  112.           rc_skip_cw
  113.            ( rcfile,
  114.              BIND_NAME_LEN+NO_OCL_CMD_OPTS*(2*BIND_NAME_LEN+2),
  115.              RCC_SIZE
  116.            );
  117.           continue;
  118.        /*}}}  */
  119.        /*{{{  comment/os-extension*/
  120.        case RC_COMMENT:
  121.        case RC_OS_EXTENSION:
  122.           while ((input=rc_get_c(rcfile)) && input!=EOF);
  123.           continue;
  124.        /*}}}  */
  125.        /*{{{  mouse-tab*/
  126.        case RC_M_TAB:
  127.          rc_skip_cw(rcfile,0,rc_get_w(rcfile));
  128.          continue;
  129.        /*}}}  */
  130.        /*{{{  marks*/
  131.        case RC_MARKS:
  132.         { char name[FOLD_PATTERN_LEN];
  133.           int i;
  134.  
  135.           /*{{{  read stored name*/
  136.           for (i=0;i<(FOLD_PATTERN_LEN-1);i++)
  137.             name[i]=rc_get_c(rcfile);
  138.           name[FOLD_PATTERN_LEN-1]='\0';
  139.           /*}}}  */
  140.           if (!strcmp(mark_mode,name))
  141.            /*{{{  reset mark-strings*/
  142.            { for (i=0;i<FOLD_TAG_LENGTH;i++) fold_open_str[i]=rc_get_c(rcfile);
  143.              for (i=0;i<FOLD_TAG_LENGTH;i++) fold_line_str[i]=rc_get_c(rcfile);
  144.              for (i=0;i<FOLD_TAG_LENGTH;i++) fold_file_str[i]=rc_get_c(rcfile);
  145.              for (i=0;i<FOLD_TAG_LENGTH;i++) fold_close_str[i]=rc_get_c(rcfile);
  146.              return(0);
  147.            }
  148.            /*}}}  */
  149.           else
  150.            /*{{{  overread the data*/
  151.            { rc_skip_cw(rcfile,4*FOLD_TAG_LENGTH,0);
  152.              continue;
  153.            }
  154.            /*}}}  */
  155.         }
  156.        /*}}}  */
  157.        /*{{{  keydef,macset,set,strings,comp-dat*/
  158.        case RC_DEFKEY:
  159.        case RC_MAC_SET:
  160.        case RC_CHARSET:
  161.        case RC_STRINGS:
  162.        case RC_REF_COMP_STR:
  163.           break;
  164.        /*}}}  */
  165.        /*{{{  error!*/
  166.        default:
  167.           fputs("incorrect rc-data,",stderr);
  168.           return(1);
  169.        /*}}}  */
  170.      }
  171.      break;
  172.    }
  173.   fputs("no matching marks found, ",stderr);
  174.   return(1);
  175. }
  176. /*}}}  */
  177.  
  178. int set_other_mark(char const * const mark_mode)
  179. {
  180.   char const *keyfile;
  181.   char base[_POSIX_PATH_MAX];
  182.   int ok;
  183.   FILE *rcfile;
  184.  
  185.   /*{{{  get base for rc file*/
  186.   if (keybase)
  187.      strcpy(base,keybase);
  188.   else
  189.      sprintf(base,BASENAMEF,"origami");
  190.   /*}}}  */
  191.   /*{{{  search for file in path list*/
  192.   keyfile=get_system_filename
  193.            ( ori_path,
  194.              base,
  195.              RC_ENDING,
  196.              (char*)0
  197.            );
  198.   /*}}}  */
  199.   if (!keyfile[0] || !(rcfile=fopen(keyfile,"r")))
  200.    { fputs("no "RC_ENDING"-file found,",stderr);
  201.      ok=1;
  202.    }
  203.   else
  204.    { ok=rc_file_parser(mark_mode,rcfile);
  205.      fclose(rcfile);
  206.    }
  207.  
  208.   return (ok);
  209. }
  210. /*}}}  */
  211. /*{{{  show_modes*/
  212. char *show_modes(struct stat const * const f)
  213. { static char coding[256];
  214.   char *s=coding;
  215.  
  216.   /*{{{  decode filetype*/
  217.   /*{{{  dir*/
  218.   if (S_ISDIR(f->st_mode))
  219.      *s++='d';
  220.   /*}}}  */
  221.   /*{{{  block special*/
  222. #  ifdef S_ISBLK
  223.   else if (S_ISBLK(f->st_mode))
  224.      *s++='b';
  225. #  endif
  226.   /*}}}  */
  227.   /*{{{  character special*/
  228. #  ifdef S_ISCHR
  229.   else if (S_ISCHR(f->st_mode))
  230.      *s++='c';
  231. #  endif
  232.   /*}}}  */
  233.   /*{{{  symbolic link*/
  234. #  ifdef S_ISLNK
  235.   else if (S_ISLNK(f->st_mode))
  236.      *s++='l';
  237. #  endif
  238.   /*}}}  */
  239.   /*{{{  fifo*/
  240. #  ifdef S_ISFIFO
  241.   else if (S_ISFIFO(f->st_mode))
  242.      *s++='p';
  243. #  endif
  244.   /*}}}  */
  245.   /*{{{  network special*/
  246. #  ifdef S_ISNWK
  247.   else if (S_ISNWK(f->st_mode))
  248.      *s++='n';
  249. #  endif
  250.   /*}}}  */
  251.   /*{{{  socket*/
  252. #  ifdef S_ISSOCK
  253.   else if (S_ISSOCK(f->st_mode))
  254.      *s++='s';
  255. #  endif
  256.   /*}}}  */
  257.   /*{{{  file*/
  258.   else if (S_ISREG(f->st_mode))
  259.      *s++='-';
  260.   /*}}}  */
  261.   /*{{{  default unknown*/
  262.   else
  263.      *s++='?';
  264.   /*}}}  */
  265.   /*}}}  */
  266.   /*{{{  decode owner/group/others permissions*/
  267.   /*{{{  owner*/
  268. #  ifdef S_IRUSR
  269.      /*{{{  read access permission for owner*/
  270.      if (S_IRUSR&f->st_mode)
  271.         *s++='r';
  272.      else
  273.         *s++='-';
  274.      /*}}}  */
  275. #  endif
  276. #  ifdef S_IWUSR
  277.      /*{{{  write access permission for owner*/
  278.      if (S_IWUSR&f->st_mode)
  279.         *s++='w';
  280.      else
  281.         *s++='-';
  282.      /*}}}  */
  283. #  endif
  284. #  ifdef S_IXUSR
  285.      /*{{{  execute/search access permission for owner*/
  286.      if (S_IXUSR&f->st_mode)
  287.         *s++='x';
  288.      else
  289.         *s++='-';
  290.      /*}}}  */
  291. #  endif
  292.   /*}}}  */
  293.   /*{{{  group*/
  294. #  ifdef S_IRGRP
  295.      /*{{{  read access permission for group*/
  296.      if (S_IRGRP&f->st_mode)
  297.         *s++='r';
  298.      else
  299.         *s++='-';
  300.      /*}}}  */
  301. #  endif
  302. #  ifdef S_IWGRP
  303.      /*{{{  write access permission for group*/
  304.      if (S_IWGRP&f->st_mode)
  305.         *s++='w';
  306.      else
  307.         *s++='-';
  308.      /*}}}  */
  309. #  endif
  310. #  ifdef S_IXGRP
  311.      /*{{{  execute/search access permission for group*/
  312.      if (S_IXGRP&f->st_mode)
  313.         *s++='x';
  314.      else
  315.         *s++='-';
  316.      /*}}}  */
  317. #  endif
  318.   /*}}}  */
  319.   /*{{{  others*/
  320. #  ifdef S_IROTH
  321.      /*{{{  read access permission for others*/
  322.      if (S_IROTH&f->st_mode)
  323.         *s++='r';
  324.      else
  325.         *s++='-';
  326.      /*}}}  */
  327. #  endif
  328. #  ifdef S_IWOTH
  329.      /*{{{  write access permission for others*/
  330.      if (S_IWOTH&f->st_mode)
  331.         *s++='w';
  332.      else
  333.         *s++='-';
  334.      /*}}}  */
  335. #  endif
  336. #  ifdef S_IXOTH
  337.      /*{{{  execute/search access permission for others*/
  338.      if (S_IXOTH&f->st_mode)
  339.         *s++='x';
  340.      else
  341.         *s++='-';
  342.      /*}}}  */
  343. #  endif
  344.   /*}}}  */
  345.   /*}}}  */
  346. # ifndef NO_POSIX_STAT
  347.      /*{{{  number of bytes and time*/
  348.      { struct passwd const *x=getpwuid(f->st_uid);
  349.        char t[27];
  350.  
  351.        strcpy(t,ctime(&f->st_mtime));
  352.        t[16]='\0';
  353.        sprintf(s," %8s%9ld %s",x?x->pw_name:"",(long)f->st_size,t+4);
  354.        while (*s) s++;
  355.      }
  356.      /*}}}  */
  357. # else
  358.      NO_POSIX_STAT
  359. # endif
  360.   *s++=' ';
  361.   *s='\0';
  362.   return(coding);
  363. }
  364. /*}}}  */
  365. /*{{{  path_get*/
  366. void path_get
  367.  ( int const absolut,
  368.    char * const dir,
  369.    char const * const cur,
  370.    char const * const ent
  371.  )
  372.  {
  373.    *dir='\0';
  374.    if (!absolut || !getcwd(dir,_POSIX_PATH_MAX))
  375.     { if (!*ent || !IS_ROOT(ent))
  376.          strcpy(dir,cur);
  377.       else
  378.          *dir='\0';
  379.       if (*dir && *ent)
  380.          strcat(dir,PATH_SEP);
  381.       strcat(dir,ent);
  382.       if (absolut)
  383.          printf("getcwd(%s): %s\n",dir,strerror(errno));
  384.     }
  385.  }
  386. /*}}}  */
  387. /*{{{  dirhandle*/
  388. /*{{{  dir_ent_cmp*/
  389. int dir_ent_cmp(const void *a, const void *b)
  390. {
  391.   return(strcmp(*((char**)a),*((char**)b)));
  392. }
  393. /*}}}  */
  394. /*{{{  forward for filehandle*/
  395. void filehandle
  396.  ( int,
  397.    char const * const name,
  398.    char const * const dir,
  399.    int const curr_depth
  400.  );
  401. /*}}}  */
  402.  
  403. void dirhandle
  404.  ( int absolut,
  405.    char const * const name,
  406.    char const * const dir,
  407.    int const curr_depth,
  408.    struct stat const * const buff
  409.  )
  410. {
  411.   if (curr_depth<=depth)
  412.    /*{{{  recursion*/
  413.    { char fn[_POSIX_PATH_MAX+1];
  414.      DIR *dirptr;
  415.  
  416.      if (absolut)
  417.       /*{{{  chdir and read*/
  418.       { if (chdir(name))
  419.            absolut=0;
  420.         else
  421.            strcpy(fn,CURR_DIR);
  422.       }
  423.       /*}}}  */
  424.      if (!absolut)
  425.       /*{{{  relative, don't change dir, combine pathname for dir*/
  426.       { if (!IS_ROOT(name))
  427.          { strcpy(fn,dir);
  428.            if (fn[0]) strcat(fn,PATH_SEP);
  429.          } 
  430.         else
  431.            fn[0]=0;
  432.         strcat(fn,name);
  433.       } 
  434.       /*}}}  */
  435.      if (fn[0])
  436.        if ((dirptr=opendir(fn))) {
  437.          /*{{{  can read the entries*/
  438.          /*{{{  local variables*/
  439.          char new_wd[_POSIX_PATH_MAX+1];
  440.          struct dirent *ls;
  441.          char **s;
  442. #         define bl_size 128
  443.          int count=0;
  444.          int curr;
  445.          int curr_size=bl_size;
  446.          int marked_point=0;
  447.          /*}}}  */
  448.  
  449.          /*{{{  get buffer for dir-entries*/
  450.          if (!(s=ORImalloc(curr_size*sizeof(char*))))
  451.             error_exit("no memory\n");
  452.          /*}}}  */
  453.          /*{{{  read the contents of the directory*/
  454.          while ((ls=readdir(dirptr))) {
  455.            /*{{{  expand entry-list*/
  456.            if (count==curr_size) {
  457.              char **old=s;
  458.              int x=0;
  459.  
  460.              if (!(s=ORImalloc((curr_size+bl_size)*sizeof(char*))))
  461.                 error_exit("no memory\n");
  462.              while (x<curr_size) {s[x]=old[x];x++;}
  463.              ORIfree(old);
  464.              curr_size+=bl_size;
  465.            }
  466.            /*}}}  */
  467.            /*{{{  get memory for entry*/
  468.            if (!(s[count]=ORImalloc(strlen(ls->d_name)+1)))
  469.               error_exit("no memory\n");
  470.            /*}}}  */
  471.            strcpy(s[count++],ls->d_name);
  472.          }
  473.          /*}}}  */
  474.          qsort((void*)s,(size_t)count,(size_t)sizeof(char*),dir_ent_cmp);
  475.          if (!single)
  476.             printf("%s  %s%s\n",
  477.                    fold_open_str,long_format?show_modes(buff):"",name);
  478.          /*{{{  get new working directory*/
  479.          path_get(absolut,new_wd,dir,name);
  480.          /*}}}  */
  481.          /*{{{  handle all entries of the directory*/
  482.          curr=0;
  483.          while (curr<count) {
  484.            if (strcmp(CURR_DIR,s[curr]) && (single || strcmp(PREV_DIR,s[curr]))) {
  485.              /*{{{  maybe mark .???*/
  486.              if (!marked_point && s[curr][0]=='.') {
  487.                marked_point=1;
  488.                printf("%s  .xxx files\n",fold_open_str);
  489.              }
  490.              /*}}}  */
  491.              /*{{{  maybe endmark .???*/
  492.              if (marked_point && s[curr][0]!='.') {
  493.                marked_point=0;
  494.                printf("%s\n",fold_close_str);
  495.              }
  496.              /*}}}  */
  497.              filehandle(absolut,s[curr],new_wd,curr_depth);
  498.              ORIfree(s[curr]);
  499.            }
  500.            curr++;
  501.          }
  502.          /*}}}  */
  503.          if (marked_point) printf("%s\n",fold_close_str);
  504.          if (!single) printf("%s\n",fold_close_str);
  505.          ORIfree(s);
  506.          closedir(dirptr);
  507.          /*}}}  */
  508.        } else
  509.          printf("cannot read this directory %s.\n",fn);
  510.      else
  511.        printf("%s cannot enter\n",name);
  512.      if (absolut) chdir(dir);
  513.    }
  514.    /*}}}  */
  515.   else
  516.     if (single)
  517.       printf("%sF %s%s\n%sF %s%s%s\n%s\n",
  518.              fold_open_str,long_format?show_modes(buff):"",name,
  519.              fold_file_str,dir,PATH_SEP,name,
  520.              fold_close_str);
  521.     else
  522.       printf("maxdepth reached for %s.\n",name);
  523. }
  524. /*}}}  */
  525. /*{{{  filehandle*/
  526. void filehandle
  527.  ( int absolut,
  528.    char const * const name,
  529.    char const * const dir,
  530.    int const curr_depth
  531.  )
  532. {
  533.  
  534. # ifdef REGEXP
  535.      if (curr_depth)
  536.         if
  537.          (    (*match_str && regexec(&preg_match,name,(size_t)0,ma,0)!=0)
  538.            || (*no_match_str && regexec(&preg_no_match,name,(size_t)0,ma,0)==0)
  539.          )
  540.            return;
  541. # endif
  542.   if (curr_depth<=depth)
  543.    { struct stat buff;
  544.      char fn[_POSIX_PATH_MAX+1];
  545.  
  546.      /*{{{  get filename for stat*/
  547.      if (absolut)
  548.         strcpy(fn,name);
  549.      else
  550.       { if (!IS_ROOT(name))
  551.          { strcpy(fn,dir);
  552.            if (fn[0]) strcat(fn,PATH_SEP);
  553.          } 
  554.         else
  555.            fn[0]='\0';
  556.         strcat(fn,name);
  557.       }
  558.      /*}}}  */
  559.      if (stat(fn,&buff))
  560.        printf("cannot stat %s=%s: %s.\n",name,name,strerror(errno));
  561.      else {
  562.        if (   ((buff.st_uid==user) && (S_IRUSR&buff.st_mode))
  563.            || ((buff.st_gid==group) && (S_IRGRP&buff.st_mode))
  564.            || (S_IROTH&buff.st_mode)
  565.            || OS_READPERM(fn,&buff)
  566.            || always )
  567.        {
  568.          /*{{{  handle a directory*/
  569.          if (S_ISDIR(buff.st_mode))
  570.             dirhandle(absolut,name,dir,curr_depth+1,&buff);
  571.          /*}}}  */
  572.          /*{{{  handle a file*/
  573.          if (S_ISREG(buff.st_mode)) {
  574.            printf("%sF %s%s\n",
  575.                   fold_open_str,
  576.                   long_format?show_modes(&buff):"",
  577.                   name);
  578.            printf("%sF %s%s%s\n",fold_file_str,dir,PATH_SEP,name);
  579.            printf("%s\n",fold_close_str);
  580.          }
  581.          /*}}}  */
  582.        } else if (mark_no_perm)
  583.          printf("no permission for %s\n",name);
  584.      }
  585.    }
  586. }
  587. /*}}}  */
  588.  
  589. /*{{{  main*/
  590. int main(int argc, char *argv[])
  591. { char call_path[_POSIX_PATH_MAX+1];
  592.   int absolut=1;
  593.   int no;
  594.  
  595.   user=geteuid();
  596.   group=getegid();
  597.   /*{{{  parse arguments*/
  598.   { int c;
  599.     char const *mark_mode=0;
  600.  
  601.     while ((c=getopt(argc,argv,"k:lm:hd:apM:srf:F:R:"))!=EOF)
  602.     switch (c)
  603.     {
  604.       /*{{{  f*/
  605.       case 'f':
  606. #        ifdef REGEXP
  607.             match_str=optarg;
  608. #        endif
  609.          break;
  610.       /*}}}  */
  611.       /*{{{  F*/
  612.       case 'F':
  613. #        ifdef REGEXP
  614.             no_match_str=optarg;
  615. #        endif
  616.          break;
  617.       /*}}}  */
  618.       /*{{{  d*/
  619.       case 'd':
  620.         if (single) d_s_error:
  621.            error_exit("d and s conflict\n");
  622.         depth=atoi(optarg);
  623.         if (depth<=0)
  624.          { puts("nothing to do.");
  625.            exit(0);
  626.          }
  627.         break;
  628.       /*}}}  */
  629.       /*{{{  l*/
  630.       case 'l':
  631.         long_format=1;
  632.         break;
  633.       /*}}}  */
  634.       /*{{{  r*/
  635.       case 'r': absolut=0;break;
  636.       /*}}}  */
  637.       /*{{{  s*/
  638.       case 's':
  639.          if (depth!=START_DEPTH)
  640.             goto d_s_error;
  641.          single=1;
  642.          depth=1;
  643.          break;
  644.       /*}}}  */
  645.       /*{{{  m*/
  646.       case 'm': mark_mode=optarg;break;
  647.       /*}}}  */
  648.       /*{{{  a*/
  649.       case 'a': always=1;break;
  650.       /*}}}  */
  651.       /*{{{  p*/
  652.       case 'p': mark_no_perm=1;break;
  653.       /*}}}  */
  654.       /*{{{  k*/
  655.       case 'k': keybase=optarg;break;
  656.       /*}}}  */
  657.       /*{{{  M*/
  658.       case 'M':
  659.        { char *s=optarg;
  660.          int k;
  661.  
  662.          for (k=0;k<FOLD_TAG_LENGTH;)
  663.             if (!(fold_open_str[k++]= *s++)) M_error:
  664.                error_exit("invalid marks given\n");
  665.          fold_open_str[FOLD_TAG_LENGTH]='\0';
  666.          for (k=0;k<FOLD_TAG_LENGTH;)
  667.             if (!(fold_file_str[k++]= *s++))
  668.                goto M_error;
  669.          fold_file_str[FOLD_TAG_LENGTH]='\0';
  670.          for (k=0;k<FOLD_TAG_LENGTH;)
  671.             if (!(fold_line_str[k++]= *s++))
  672.                goto M_error;
  673.          fold_line_str[FOLD_TAG_LENGTH]='\0';
  674.          for (k=0;k<FOLD_TAG_LENGTH;)
  675.             if (!(fold_close_str[k++]= *s++))
  676.                goto M_error;
  677.          fold_close_str[FOLD_TAG_LENGTH]='\0';
  678.          if (*s)
  679.             goto M_error;
  680.          break;
  681.        }
  682.       /*}}}  */
  683.       /*{{{  R*/
  684.       case 'R':
  685.          ori_path=optarg;
  686.          break;
  687.       /*}}}  */
  688.       /*{{{  h and error*/
  689.       default:
  690.       case '?':
  691.         fputs("dirfold: invalid option\n",stderr);
  692.       case 'h':
  693.         fputs
  694.          ( "Usage:\tdirfold [-ahlpsr] [-d depth]"
  695. #          ifdef REGEXP
  696.               " [-f match]"
  697. #          endif
  698.            " [-k namebase]\n\t[-m markname]"
  699. #          ifdef REGEXP
  700.               " [-F nomatch]"
  701. #          endif
  702.            " [-M markpatterns] [-R "RC_ENDING"-path-list]\n\t[filename] ...\n",
  703.            stderr
  704.          );
  705.         exit((c=='h')?0:1);
  706.       /*}}}  */
  707.     }
  708. #   ifdef REGEXP
  709.     /*{{{  handle [no_]match string*/
  710.       if (*match_str)
  711.        /*{{{  compile*/
  712.        { if
  713.           (    regcomp
  714.                 ( &preg_match,
  715.                   match_str,
  716.                   USE_NOSUB(0)|REG_EXTENDED|USE_SUB_LIMIT(0,preg_match)
  717.                 )
  718.             != 0
  719.           )
  720.             error_exit("dirfold: invalid match expression\n");
  721.        }
  722.        /*}}}  */
  723.       if (*no_match_str)
  724.        /*{{{  compile*/
  725.        { if
  726.           (    regcomp
  727.                 ( &preg_no_match,
  728.                   no_match_str,
  729.                   USE_NOSUB(0)|REG_EXTENDED|USE_SUB_LIMIT(0,preg_match)
  730.                 )
  731.             != 0
  732.           )
  733.             error_exit("dirfold: invalid no-match expression\n");
  734.        }
  735.        /*}}}  */
  736.     /*}}}  */
  737. #   endif
  738.     /*{{{  no marks found*/
  739.     if (mark_mode && set_other_mark(mark_mode))
  740.        error_exit("dirfold: mark conflict\n");
  741.     /*}}}  */
  742.   }
  743.   /*}}}  */
  744.   path_get(absolut,call_path,"","");
  745.   if (argv[no=optind])
  746.      do
  747.         filehandle(absolut,argv[no],call_path,0);
  748.      while (argv[++no]);
  749.   else
  750.      filehandle(absolut,CURR_DIR,call_path,0);
  751.   if (call_path[0])
  752.      chdir(call_path);
  753.   return(0);
  754. }
  755. /*}}}  */
  756.