home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / dskutl / syscop.cq / SYSCOP.C
Text File  |  1985-06-13  |  10KB  |  349 lines

  1. /*
  2.  * SYSCOPY - a portable replacement for the CP/M SYSGEN utility
  3.  * This program uses the disk parameter tables in CP/M 2.x if
  4.  * possible, but can also be configured to prompt for CP/M 1.x
  5.  * The input and output files are biased to 0900h so that they
  6.  * can be loaded and debugged with DDT/SID ala the documentation
  7. */
  8. #include "bdscio.h"
  9. #define    INPUT    0
  10. #define    OUTPUT    1
  11. #define    UPDATE    2
  12. #define    SELDSK    9
  13. #define    SETTRK    10
  14. #define    SETSEC    11
  15. #define    SETDMA    12
  16. #define    READS    13
  17. #define    WRITES    14
  18. #define    VERSION    12
  19. #define    CURRENT    25
  20. #define    READR    33
  21. #define    WRITER    34
  22. #define    COMFSZ    35
  23. #define    dpb    struct DPB
  24. struct    DPB    {
  25.     int        dpb_spt;
  26.     char    dpb_bsh;
  27.     char    dpb_blm;
  28.     char    dpb_exm;
  29.     unsigned    dpb_dsm;
  30.     unsigned    dpb_drm;
  31.     char    dpb_al0;
  32.     char    dpb_al1;
  33.     int        dpb_cks;
  34.     int        dpb_off;
  35.     };
  36. #define    dph    struct DPH
  37. struct    DPH    {
  38.     unsigned    dph_xlt;
  39.     char    dph_res11[6];
  40.     char    *dph_dirbuf;
  41.     dpb        *dph_dpb;
  42.     char    *dph_csv;
  43.     char    *dph_alv;
  44.     };
  45. #define    DRIVES    "ABCDEFGHIJKLMNOP"
  46. #define    MAXINT    32767
  47. #define MAXSYS    64
  48.  
  49. main(argc,argv)
  50. int argc;
  51. char *argv[];
  52.     {
  53.     char source[32],destination[32],number[32],reply[32]; /* plenty big */
  54.     int fromdisk,todisk; /* signal file or direct I/O */
  55.     int version,inres,outres,inspt,outspt,indrive,outdrive;
  56.     int i,count,infd,outfd,insec,outsec,intrk,outtrk,insize,outsize;
  57.     dph *indph,*outdph;
  58.     dpb *indpb,*outdpb;
  59.     char current,buffer[SECSIZ],system[MAXSYS][SECSIZ];
  60.  
  61. /*
  62.  * Output the signon message, init, and check for a help request
  63. */
  64.     current = bdos(CURRENT,0); /* get current disk number */
  65.     version = bdos(VERSION,0); /* get the CP/M version number */
  66.     if ((argc > 1) && (argv[1][0] == '?'))
  67.     {
  68.     printf("Syscopy utility version 1.0 - by Stephen M. Kenton\n\n");
  69.     printf("Syntax: syscpy [input [output [count]]]\n");
  70.     printf("Input and output may be either a disk or a filename\n");
  71.     printf("If specified, a colon ':' must be included with a disk\n");
  72.     printf("name, or it will be considered to be a short file name\n");
  73.     printf("Count is the number of sectors to be read and written\n");
  74.     printf("It will normally be 1 for the boot block or '*' for all\n");
  75.     printf("Count may be in decimal, or preceeded by a $ for hex\n");
  76.     printf("Any argument(s) that are omitted will be prompted for\n");
  77.     exit(0);
  78.     }
  79.     printf("Portable system copy utility. For help, enter 'syscopy ?'\n\n");
  80.  
  81. /*
  82.  * Get the input arguments from the command line or the user
  83. */
  84.     if (argc > 1)
  85.     strcpy(source,argv[1]);
  86.     else
  87.     {
  88.     printf("Enter source, or return for current drive: ");
  89.     gets(source);
  90.     }
  91.     if (strlen(source) == 0)
  92.     {
  93.     source[0] = DRIVES[current]; /* fabricate a string */
  94.     strcpy(source+1,":");
  95.     }
  96.     if ((strlen(source) == 2) && (source[1] == ':'))
  97.     {
  98.     fromdisk = TRUE;
  99.     indrive = index(DRIVES,toupper(source[0]));
  100.     }
  101.     else
  102.     fromdisk = FALSE;
  103.  
  104.     if (argc > 2)
  105.     strcpy(destination,argv[2]);
  106.     else
  107.     {
  108.     printf("Enter destination, or return for current drive: ");
  109.     gets(destination);
  110.     }
  111.     if (strlen(destination) == 0)
  112.     {
  113.     destination[0] = DRIVES[current]; /* fabricate a string */
  114.     strcpy(source+1,":");
  115.     }
  116.     if ((strlen(destination) == 2) && (destination[1] == ':'))
  117.     {
  118.     todisk = TRUE;
  119.     outdrive = index(DRIVES,toupper(destination[0]));
  120.     }
  121.     else
  122.     todisk = FALSE;
  123.  
  124.     if (argc > 3)
  125.     strcpy(number,argv[3]);
  126.     else
  127.     {
  128.     printf("Enter number of sectors, or return for all: ");
  129.     gets(number);
  130.     }
  131.     if (strlen(number) == 0)
  132.     {
  133.     strcpy(number,"*"); /* asterisk means copy all sectors */
  134.     }
  135.     if (number[0] == '*') /* wild card */
  136.     count = MAXINT; /* largest possible value */
  137.     else if (number[0] == '$') /* hexidecimal */
  138.     sscanf(number+1,"%x",&count);
  139.     else /* decimal */
  140.     sscanf(number,"%d",&count);
  141.  
  142. /*
  143.  * Now determine the characteristics of the drives or files
  144. */
  145.     if ((version == 0) || (version > 255)) /* CP/M 1.x or MP/M */
  146.     {
  147.     printf("MP/M does not allow access to some disk I/O calls,  and\n");
  148.     printf("CP/M 1.x does not supply some needed information\n");
  149.     printf("for this utility to run, use CP/M 2.x to run it\n");
  150.     exit(1);
  151.     }
  152.     else
  153.     {
  154.     if (fromdisk) /* if reading from the system tracks */
  155.         {
  156.         indph = dphaddr(indrive); /* DPH address */
  157.         if (indph == 0)
  158.         {
  159.         printf("Invalid source drive %s selected\n",source);
  160.         exit(1);
  161.         }
  162.         indpb = indph->dph_dpb; /* DPB address */
  163.         inres = indpb->dpb_off; /* number of reserved tracks */
  164.         inspt = indpb->dpb_spt; /* number of sectors per track */
  165.         insize = inres * inspt; /* number of reserved sectors */
  166.         if (inres > 3)
  167.         {
  168.         printf("There are more than 3 reserved tracks on this drive\n");
  169.         printf("This normally indicates that it is a logical disk\n");
  170.         printf("rather than a bootable physical disk volume\n");
  171.         printf("If this is the case, reading the reserved tracks\n");
  172.         printf("will result in garbage being in the buffer\n");
  173.         printf("Do you with to continue? (Y/N): ");
  174.         scanf("%s",reply); /* get the response */
  175.         if (toupper(reply[0]) != 'Y')
  176.             exit(1);
  177.         }
  178.         }
  179.     else /* if reading from a file */
  180.         {
  181.         if ((infd = open(source,INPUT)) == ERROR)
  182.         {
  183.         printf("Can not open source file %s\n",source);
  184.         exit(1);
  185.         }
  186.         insize = rcfsiz(infd) - 16; /* file size - bias */
  187.         for (i=0; i<16; i++)
  188.         read(infd,buffer,1); /* dump the bias sectors */
  189.         }
  190.  
  191.     if (todisk) /* if writing to the system tracks */
  192.         {
  193.         outdph = dphaddr(outdrive); /* DPH address */
  194.         if (outdph == 0)
  195.         {
  196.         printf("Invalid destination drive %s selected\n",destination);
  197.         exit(1);
  198.         }
  199.         outdpb = outdph->dph_dpb; /* DPB address */
  200.         outres = outdpb->dpb_off;
  201.         outspt = outdpb->dpb_spt;
  202.         outsize = outres * outspt; /* number of reserved sectors */
  203.         if (inres > 3)
  204.         {
  205.         printf("There are more than 3 reserved tracks on this drive\n");
  206.         printf("This normally indicates that it is a logical disk\n");
  207.         printf("rather than a bootable physical disk volume\n");
  208.         printf("If this is the case, writing on the reserved\n");
  209.         printf("tracks will destroy another logical disk\n");
  210.         printf("Do you with to continue? (Y/N): ");
  211.         scanf("%s",reply); /* get the response */
  212.         if (toupper(reply[0]) != 'Y')
  213.             exit(1);
  214.         }
  215.         }
  216.     else /* if writing to a file */
  217.         {
  218.         if ((outfd = creat(destination)) == ERROR)
  219.         {
  220.         printf("Can not open destination file %s\n",destination);
  221.         exit(1);
  222.         }
  223.         outsize = MAXINT; /* largest possible value */
  224.         setmem(buffer,SECSIZ,'\0'); /* clear the buffer */
  225.         for (i=0; i<16; i++)
  226.         write(outfd,buffer,1); /* write the bias sectors */
  227.         }
  228.     }
  229.     insize = (count < insize) ? count : insize; /* choose  the smaller */
  230.     if (insize > outsize)
  231.     {
  232.     printf("Source is longer than destination, truncate? (Y/N): ");
  233.     scanf("%s",reply); /* check answer */
  234.     if (toupper(reply[0]) == 'Y')
  235.         insize = outsize;
  236.     else
  237.         exit(1);
  238.     }
  239.     if (insize > MAXSYS)
  240.     {
  241.     printf("System size exceeds memory buffer limit\n");
  242.     exit(1);
  243.     }
  244.  
  245. /*
  246.  * Copy the source to the destination
  247. */
  248.     outsize = insize; /* write only as much as was specified */
  249.     if (fromdisk) /* read from the system tracks */
  250.     {
  251.     bios(SELDSK,indrive); /* select the input drive */
  252.     for (intrk=0; intrk<inres; intrk++)
  253.         {
  254.         bios(SETTRK,intrk); /* select the track */
  255.         for (insec=1; insec<=inspt; insec++)
  256.         {
  257.         count = intrk*inspt+insec-1; /* number of sectors */
  258.         if (count > insize)
  259.             goto stopin; /* we just hit the limit */
  260.         bios(SETSEC,insec); /* set the sector number */
  261.         bios(SETDMA,system[count]); /* set DMA address */
  262.         bios(READS,0); /* read the sector in */
  263.         }
  264.         }
  265.     stopin:
  266.     bios(SELDSK,current); /* select the origianal drive */
  267.     }
  268.     else /* read from a file */
  269.     {
  270.     if (read(infd,system,insize) < insize) /* read what you need */
  271.         {
  272.         printf("Error reading %s\n",source);
  273.         exit(1);
  274.         }
  275.     }
  276.  
  277.     if (todisk) /* write to the system tracks */
  278.     {
  279.     bios(SELDSK,outdrive); /* select the output drive */
  280.     for (outtrk=0; outtrk<outres; outtrk++)
  281.         {
  282.         bios(SETTRK,outtrk); /* select the track */
  283.         for (outsec=1; outsec<=outspt; outsec++)
  284.         {
  285.         count = outtrk*outspt+outsec-1; /* number of sectors */
  286.         if (count > outsize)
  287.             goto stopout; /* we just hit the limit */
  288.         bios(SETSEC,outsec); /* set the sector */
  289.         bios(SETDMA,system[count]); /* set DMA address */
  290.         bios(WRITES,0); /* write the sector */
  291.         }
  292.         }
  293.     stopout:
  294.     bios(SELDSK,current); /* select the original drive */
  295.     }
  296.     else /* write to a file */
  297.     {
  298.     if (write(outfd,system,outsize) < outsize) /* write what you have */
  299.         {
  300.         printf("Error writing %s\n",destination);
  301.         exit(1);
  302.         }
  303.     }
  304.  
  305. /*
  306.  * Clean up and exit
  307. */
  308.     if (!fromdisk) /* if reading from a file */
  309.     close(infd);
  310.     if (!todisk) /* if writing to a file */
  311.     close(outfd);
  312.     printf("%d sectors were copied from %s to %s\n",insize,source,destination);
  313.     }
  314.  
  315. /*
  316.  * Index - return the index of the first occurance of a char in a
  317.  * string, or ERROR if it is not found
  318. */
  319. index(str,c)
  320. char *str,c;
  321.     {
  322.     int i;
  323.     for (i=0; str[i]; i++)
  324.     {
  325.     if (str[i] == c)
  326.         return(i); /* found it */
  327.     }
  328.     return(ERROR); /* did not find it */
  329.     }
  330.  
  331. /*
  332.  * Dphaddr - return the address of a disk parameter header
  333.  * This is performed by bios call 9, but the Bios() function
  334.  * can not be used, because it returns a <A> not <HL>
  335. */
  336. dphaddr(drive)
  337. int drive;
  338.     {
  339.     unsigned *warmstart,seldsk,result;
  340.     char current;
  341.  
  342.     current = bdos(CURRENT,0); /* save the current drive */
  343.     warmstart = 1;
  344.     seldsk = *warmstart + 24; /* address of SELDSK routine */
  345.     result = call(seldsk,0,0,drive,0); /* call the bios seldsk routine */
  346.     bios(SELDSK,current); /* restore the original disk */
  347.     return(result);
  348.     }
  349.