home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol144 / rename.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-04-29  |  6.7 KB  |  322 lines

  1. /*
  2.  
  3.     WILDCARD FILE RENAME PROGRAM
  4.  
  5.     By David Brown, Australia
  6.  
  7. Version list, most recent version first
  8.  
  9. 21/Jul/83
  10.     Expanded usage message so that it gave meaningful help.
  11.     Version list and this descriptive header added,
  12.     Version 2.1, Bill Bolton
  13.  
  14.     Fixed initial bugs in version 1. Version 2, David Brown
  15.  
  16.     Initial implementation, placed on "Software Tools" RCPM.
  17.     Version 1, David Brown
  18.  
  19. */
  20.  
  21. #include <bdscio.h>
  22. #include <bdos.h>
  23.  
  24. #define VERSION "2.1"    /* version 1 didn't work */
  25. #define FCBSIZ 36    /* size of a CP/M File Control Block */
  26. #define NAMLEN 20    /* should be plenty for a filename */
  27.  
  28.  
  29.         char oldfcb[FCBSIZ], newfcb[FCBSIZ];
  30.  
  31. #define LIST struct lst_entry
  32. #define LISTSIZ (NAMLEN+2)
  33. LIST {
  34.     char    name[NAMLEN];    /* name in CP/M format e.g. 1/B:FOO.BAR */
  35.         LIST    *next;
  36. };
  37.     LIST *o_head, *n_head, *a_head;   /* lists of filenames */
  38.  
  39.     char    def_usr;    /* saves the current user area */
  40.     char    def_drv;
  41.     int    count;        /* counts how many renames were done */
  42.  
  43. main(argc, argv)
  44. char **argv;
  45. {
  46.  
  47.     char usr_new, usr_old;
  48.     char drv_new, drv_old;
  49.  
  50.     count = 0;
  51.  
  52.     def_usr = bdos(USERCODE,0xff);
  53.     def_drv = bdos(GETCURRENT);   /* 0=A 1=B ... */
  54.  
  55.     o_head = n_head = a_head = NULL;
  56.  
  57.     printf("\nCP/M 'Wildcard' File Rename Utility, Version %s\n",VERSION);
  58.         if (argc != 3) {
  59.         printf("\nUsage:\n");
  60.         printf("\tRENAME filename1 filename2\n\n");
  61.         printf("Where:\tfilename1\tis any legal CP/M 'ambiguous' file identifier\n");
  62.         printf("\t\t\tand is the 'NEW' filename\n\n");
  63.         printf("\tfilename2\tis any legal CP/M 'ambiguous' file identifier\n");
  64.         printf("\t\t\twith the wildcard characters in the same place\n");
  65.         printf("\t\t\tas filename1. It is the 'EXISTING' filename\n\n");
  66.         printf("Note:\t? and * are wildcard characters in CP/M file indentifiers\n\n");
  67.         printf("See RENAME.DOC for a full explanation of command line syntax\n\n");
  68.         bye(ERROR);
  69.         }
  70.  
  71.     usr_new = stripusr(&argv[1]);  /* remove user area prefix, */
  72.     usr_old = stripusr(&argv[2]);  /*   if it is there.. */
  73.     if (usr_new != usr_old) {
  74.         printf("\nUser areas must be the same\n");
  75.         bye(ERROR);
  76.     }
  77.  
  78.     drv_new = stripdrv(&argv[1]);    /* remove drive prefixes */
  79.     drv_old = stripdrv(&argv[2]);
  80.     if (drv_new != drv_old) {
  81.         printf("\nDrives must be the same\n");
  82.         bye(ERROR);
  83.     }
  84.  
  85.     setfcb(oldfcb,argv[2]); /* make up the fcb's */
  86.     setfcb(newfcb,argv[1]);
  87.     if (chkwild() == ERROR) {
  88.         printf("\nNames must be 'ambiguous' in a reasonable way.\n\n");
  89.         printf("See RENAME.DOC file for a definition of \"reasonable\"\n");
  90.         bye(ERROR);
  91.         }
  92.  
  93.     bdos(SELECTDISK,drv_new);  /* change to required drive */
  94.     bdos(USERCODE,usr_new);   /* and user area          */
  95.  
  96.         makeold();      /* generate list of old names */
  97.         makenew();
  98.         makeall();      /* generate list of all filenames */
  99.  
  100.     dorens();    /* rename all the files */
  101.  
  102.     if (count)
  103.         printf("\n%d files renamed.\n",count);
  104.     else
  105.         printf("\nNo files renamed.\n");
  106.  
  107.     bye(OK);
  108. }
  109.  
  110. bye(status)
  111. {
  112.     bdos(SELECTDISK,def_drv);    /* reset drive and user */
  113.     bdos(USERCODE,def_usr);
  114.     exit(status);
  115. }
  116.  
  117. char stripusr(s)
  118. char **s;    /* need ptr to ptr as will update it */
  119. {
  120.  
  121.     char *t;    /* scan ptr */
  122.     int  usr;
  123.  
  124.     t = *s;
  125.     while (isdigit(*t))  /* advance to first non-numeric */
  126.         t++;
  127.     if (*t++ != '/')
  128.         return def_usr; /* no user area prefix */
  129.  
  130.     usr = atoi(*s); /* get user area */
  131.  
  132.     if (usr > 31 || usr < 0)    /* not possible, thus must be part of */
  133.         return def_usr;     /*    name, so go back with default */
  134.  
  135.     *s = t;     /* delete prefix from our input string */
  136.     return usr;
  137. }
  138.  
  139. chkwild()    /* ensures that are wild in correct manner - see .DOC */
  140. {
  141.     char i;
  142.  
  143.     for (i=0; i<12; i++)
  144.         if (oldfcb[i] != '?' && newfcb[i] == '?')
  145.             return ERROR;
  146. }
  147.  
  148. char stripdrv(s)
  149. char **s;    /* need ptr to ptr as will update it */
  150. {
  151.  
  152.     int  drv;
  153.  
  154.     if ((*s)[1] != ':')       /* no drive prefix if no colon */
  155.         return def_drv;
  156.  
  157.     drv = toupper(**s) - 'A';
  158.     if (drv < 0 || drv > 15)
  159.         return def_drv;
  160.  
  161.     *s += 2;    /* advance past drive */
  162.  
  163.     return drv;
  164.  
  165. }
  166.  
  167. makeold()
  168. {
  169.  
  170.     char dma[SECSIZ], nme[NAMLEN];
  171.     char index;    /* returned by search function */
  172.  
  173.     bdos(SETADDRESS,dma);
  174.  
  175.     index = bdos(SEARCHFIRST,oldfcb);
  176.     while (index != 255) {
  177.         unsetfcb(dma+index*32,nme);
  178.         addlst(&o_head,nme);
  179.         index = bdos(SEARCHNEXT,oldfcb);
  180.     }
  181. }
  182.  
  183. makenew()
  184. {
  185.     char o_fcb[FCBSIZ];    /* holds ufn of current old file */
  186.     char n_fcb[FCBSIZ];    /*  "      "   "    "    new  "     */
  187.     char nme[NAMLEN];
  188.  
  189.     LIST *trav;
  190.     int  i;
  191.  
  192.     trav = o_head;
  193.     while (trav != NULL) {        /* traverse old names */
  194.         setfcb(o_fcb,trav->name);
  195.         for (i=1;i<12;i++) {    /* scan the wild version */
  196.             if (oldfcb[i]=='?') {        /* needs to change ? */
  197.                 if (newfcb[i] == '?')       /* yes .. */
  198.                     n_fcb[i]=o_fcb[i];
  199.                 else
  200.                     n_fcb[i]=newfcb[i];
  201.             } else
  202.                 n_fcb[i]=newfcb[i];  /* No, just copy */
  203.         }
  204.         unsetfcb(n_fcb,nme);
  205.         addlst(&n_head,nme);
  206.         trav = trav->next;
  207.     }
  208. }
  209.  
  210. makeall()
  211. {
  212.  
  213.     char dma[SECSIZ], nme[NAMLEN], fcb[FCBSIZ];
  214.     char index;    /* returned by search function */
  215.  
  216.  
  217.     setfcb(fcb,"*.*");    /* all files */
  218.  
  219.     bdos(SETADDRESS,dma);
  220.  
  221.     index = bdos(SEARCHFIRST,fcb);
  222.     while (index != 255) {
  223.         unsetfcb(dma+index*32,nme);
  224.         addlst(&a_head,nme);
  225.         index = bdos(SEARCHNEXT,fcb);
  226.     }
  227. }
  228.  
  229. dorens()    /* do actual renames */
  230. {
  231.  
  232.     char ch;
  233.  
  234.     while (o_head) {
  235.         if (exists(n_head)) {    /* if exists, what do I do now ? */
  236.             printf("%s to %s, exists - ",
  237.                     o_head->name,n_head->name);
  238.             printf("(Q)uit,(S)kip,(K)ill : ");
  239.             scanf("%c",&ch);
  240.             switch(toupper(ch)) {
  241.                 case 'Q' : bye(ERROR);
  242.                 case 'K' : unlink(n_head->name);
  243.                        rename(o_head->name,n_head->name);
  244.             }
  245.         } else {
  246.             rename(o_head->name,n_head->name);
  247.             count++;
  248.         }
  249.         o_head = o_head->next;
  250.         n_head = n_head->next;
  251.     }
  252. }
  253.  
  254. unsetfcb(f,n)    /* do opposite of "setfcb". This IGNORES the drive field */
  255. char *f, *n;
  256. {
  257.     char *f_save;
  258.  
  259.     f_save = f++;    /* save initial pos and ignore drive */
  260.  
  261.     while (*f != ' ' && f < f_save+9)
  262.         *n++ = *f++;    /* copy till a blank */
  263.     *n++ = '.';
  264.     f = f_save + 9; /* point at type */
  265.     while (*f != ' ' && f < f_save+12)
  266.         *n++ = *f++;
  267.     *n = '\0';
  268. }
  269.  
  270. addlst(h,n)
  271. char **h, *n;
  272. {
  273.  
  274.     char *trav;
  275.  
  276.     trav = *h;
  277.  
  278.     if (*h == NULL) {
  279.         *h = getmem(LISTSIZ);
  280.         (*h)->next = NULL;
  281.         strcpy((*h)->name,n);
  282.     } else {
  283.         trav = *h;
  284.         while (trav->next != NULL)
  285.             trav = trav->next;
  286.         trav->next = getmem(LISTSIZ);
  287.         trav = trav->next;
  288.         trav->next = NULL;
  289.         strcpy(trav->name,n);
  290.     }
  291. }
  292.  
  293. char *getmem(n)
  294. {
  295.     char *s;
  296.     s = alloc(n);
  297.     if (!s) {
  298.         printf("\nOut of memory - see notes RENAME.C source file\n");
  299.         bye(ERROR);
  300.         /* this will only happen if you have a lot of
  301.             directory entries that need to be matched
  302.             e.g. for 128 entries, need 20K free at MOST
  303.             otherwise I have a bug
  304.         */
  305.     }
  306.     return s;
  307. }
  308.  
  309. exists(n)    /* does n exist in list of all files in drive/user */
  310. char *n;
  311. {
  312.  
  313.     LIST *trav;
  314.  
  315.     trav = a_head;
  316.     while (trav) {
  317.         if (strcmp(trav->name,n) == 0)
  318.             return TRUE;
  319.         trav = trav->next;
  320.     }
  321.     return FALSE;
  322. }