home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 193_01 / backup.c < prev    next >
Text File  |  1985-11-14  |  17KB  |  354 lines

  1. /*-----------------------------------------------------------------*/
  2. /*  PROGRAMME  ==>  backup.c                                       */
  3. /*  Will back up any files which don't have the archive bit        */
  4. /*  ( = t3) already set.                                           */
  5. /*  VERSION:  1.3       Written:  13th July, 1986                  */
  6. /*  -------             -------   Phil. E. Cogar                   */
  7. /*                                                                 */
  8. /*  Note: It uses an 8K buffer to do the file transfers            */
  9. /*  ----                                                           */
  10. /*  Usage is -                                                     */
  11. /*                 backup [d1] [d2]                                */
  12. /*                                                                 */
  13. /*  where, "d1" and "d2" are drive names.                          */
  14. /*                                                                 */
  15. /*  This programme uses the CP/M functions -                       */
  16. /*                                                                 */
  17. /*                 15   open file                                  */
  18. /*                 16   close file                                 */
  19. /*                 17   search first                               */
  20. /*                 18   search next                                */
  21. /*                 19   erase file                                 */
  22. /*                 26   set DMA address                            */
  23. /*                 30   set file attributes                        */
  24. /*  which will be found in the file DEFF3 and which will be added  */
  25. /*  automatically to the "COM" file when you use CLINK.            */
  26. /*                                                                 */
  27. /*  to do the required work.                                       */
  28. /*  Written by:         Phil Cogar - July 12, 1986                 */
  29. /*  ----------                                                     */
  30. /*  Copyright 1986 - Cogar Computer Services Pty.Ltd.              */
  31. /*-----------------------------------------------------------------*/
  32. #include <bdscio.h>    /* NOTE: This programme is specific to     */
  33.             /* ----  BDS 'C'.   If you use a different */
  34.             /*       C then you must change this line. */
  35. #include <pec.h>    /* Required for this file                  */
  36. /*-----------------------------------------------------------------*/
  37. #define SECTORS 64    /* To be used in 8K buffer, transfer_buf   */
  38. #define VERSION "1.3"    /* Current version number                  */
  39. char    transfer_buf[SECTORS*128]; /* which is for the copy part   */
  40.                    /* of the programme.            */
  41. /*-----------------------------------------------------------------*/
  42.  
  43. main(argc,argv)
  44. short argc;
  45. char *argv[];
  46. {
  47. /*  The defined values used in the programme                       */
  48. /*-----------------------------------------------------------------*/
  49.     char fcb[36];    /* Use for the ambiguous file mask         */
  50.     short drive1, drive2, d1, d2;    /* The nominated drives.   */
  51.     char name_buf[3200];    /* Use to hold the file names      */
  52.                     /* Note present limit of 100       */
  53.     char fcb1[36];    /* The file control blocks                 */
  54.     char fcb2[36];    /* used in the file_copy routine           */
  55.     char dma[128];    /* The DMA buffer for CP/M to use  */
  56.     char mode[4];    /* The file mode                           */
  57.         mode[0] = 'A';  /* I know it can be done more      */
  58.         mode[1] = 'R';  /* elegantly, but this makes it    */
  59.         mode[2] = 'C';    /* clear that mode = "ARC"         */
  60.         mode[3] = '\0';    /* with NULL terminator.           */
  61.     short count, file_count, i, j, k, n; /* counters             */
  62.     short value;        /* General purpose function return */
  63.     short offset;    /* Used in recovering the names from the   */
  64.             /* name_buf, where we store them.          */
  65.     short pointer;    /* Used in transferring data to-and-from   */
  66.             /* the transfer buffer.                    */
  67. /*-----------------------------------------------------------------*/
  68. /*  The programme proper starts here.                              */
  69. /*  First construct the ambiguous search mask  for use in the      */
  70. /*  CP/M "search first" and "search next" routines                 */
  71. /*-----------------------------------------------------------------*/
  72.  
  73.     fcb[0] = '\0';    /* Note: Drive not allocated yet           */
  74.     for(i = 1; i < 12; i++)
  75.         fcb[i] = '?';
  76.     for(i = 12; i < 36; i++)
  77.         fcb[i] = '\0';
  78.         
  79.     
  80.     offset = file_count = 0;    /* starting values         */
  81.  
  82.     pec_clear();    /* clear the screen to start */
  83.     sign_on();    /* and put sign-on message                 */
  84.  
  85. /*-----------------------------------------------------------------*/
  86. /*  Now set the DMA buffer for transfer of information to and from */
  87. /*  the nominated drives.   This buffer will be used throughout    */
  88. /*  the programme whenever a file is accessed.                     */
  89. /*-----------------------------------------------------------------*/
  90.  
  91.     set_dma(dma);
  92.     
  93. /*-----------------------------------------------------------------*/
  94. /*  The programme proper starts here.   First see whether the two  */
  95. /*  drive names have been  entered.                                */
  96. /*-----------------------------------------------------------------*/
  97.  
  98.     if(argc < 3)    /* check to see if both drive names given  */
  99.     {
  100.         drive1 = mess1(drive1); /* and if not then we have */
  101.         drive2 = mess2(drive2); /* to ask for them         */
  102.     }
  103.     else if(argc == 3)
  104.     {
  105.         drive1 = toupper(*argv[1]);
  106.         drive2 = toupper(*argv[2]);
  107.     }
  108.     else mess3(); /* Otherwise you've screwed up somehow.      */
  109.  
  110. /*-----------------------------------------------------------------*/
  111. /*  Now check to see whether valid drive names were entered.       */
  112. /*  This programme only recognises drives A, B, C and D.   If you  */
  113. /*  have other drives change "check_drive" to suit.                */
  114. /*-----------------------------------------------------------------*/
  115.  
  116.     check_drive(drive1);
  117.     check_drive(drive2);
  118.  
  119. /*-----------------------------------------------------------------*/
  120. /*  For the programme to work the drive names have to be different */
  121. /*  so now check that they are, else quit.                         */
  122. /*-----------------------------------------------------------------*/
  123.  
  124.     if(drive1 == drive2)
  125.         mess4();
  126.  
  127. /*-----------------------------------------------------------------*/
  128. /*  Now convert the drive names to CP/M format and use the search  */
  129. /*  first and search next functions to collect those names where   */
  130. /*  the t3 character doesn't have bit 7 set.   Save these names    */
  131. /*  into the name buffer                                           */
  132. /*-----------------------------------------------------------------*/
  133.  
  134.     d1 = drive1 - 'A' + 1;    /* Convert drives to CP/M format   */
  135.     d2 = drive2 - 'A' + 1;
  136.  
  137.     fcb[0] = d1;    /*  Put FROM drive into search mask then   */
  138.             /*  call the search first routine          */
  139.  
  140.     if((i = search_first(fcb)) != 255)
  141.     {
  142.         count = save_name(i, dma, name_buf, offset);
  143.         file_count = file_count + count;
  144.         if(count)
  145.             offset = offset + 32;
  146.     }
  147.     else mess5();
  148.  
  149.  
  150.     while((i = search_next()) != 255) /* Now do search next    */
  151.     {
  152.         count = save_name(i, dma, name_buf, offset);
  153.         file_count = file_count + count;
  154.         if(count)
  155.             offset = offset + 32;
  156.     }
  157.  
  158. /*-----------------------------------------------------------------*/
  159. /*  Now check the name buffer and see if any files were found to   */
  160. /*  copy.   If not then quit.                                      */
  161. /*-----------------------------------------------------------------*/
  162.  
  163.     if(file_count == 0)
  164.         mess6();
  165.  
  166. /*-----------------------------------------------------------------*/
  167. /*  If we get to here then there are some files to be archived so  */
  168. /*  we can now start to copy these across to the back-up drive.    */
  169. /*-----------------------------------------------------------------*/
  170.  
  171.     printf("\n\nStart of copying\n");
  172.     printf("----------------\n\n");
  173.  
  174.     offset = 0;    /*  SüÄü at beginning of name buffer      */
  175.     for(n = 0; n < file_count; n++)
  176.     {
  177. /*-----------------------------------------------------------------*/
  178. /*  Now put the name into the two file control blocks so that it   */
  179. /*  can be used in the READ/WRITE functions which follow.          */
  180. /*-----------------------------------------------------------------*/
  181.     fcb_zero(fcb1);    /* clear the file control blocks           */
  182.     fcb_zero(fcb2);
  183.     
  184.     for(k = 0; k < 12; k++)
  185.         fcb1[k] = name_buf[offset + k];
  186.     fcî╞RAHAM -2 LINCOLN -3
  187.  
  188. then the decryption runstring would be 
  189.  
  190.           cypher file.new file.doc -3 LINCOLN -2 ABRAHAM
  191.  
  192.  
  193. FV.C - LISTING #5
  194.  
  195. As I mentioned earlier,  this is my replacement for the CP/M dump 
  196. utility.  It  allows  the user to pass one or two  files  in  the 
  197. runstring  for  display.  If  one  file name  is  passed  in  the 
  198. runstring,  the output appears much like the CP/M dump.com output 
  199. with  the  addition of the ascii display.  If two file names  are 
  200. passed,  the output consists of a line from file one, a line from 
  201. file  two and a third line containing the exclusive oring of  the 
  202. two files (labeled "dif"). In all cases, non printable characters 
  203. are  replaced with a carrot ( ^ ) in the ascii portion and  nulls 
  204. are  replaced  with an  equal sign ( =  ),  to  readily  identify 
  205. comparisons between two files. The comparative output is purely a 
  206. byte  for  byte operation and no attempt is made to  realign  the 
  207. file  to comparing characters as in a compare utility.  The first 
  208. file length controls display length.  Figures 1 shows an  example 
  209. of  screen output from the runstring <fv cypher1.c>  and Figure 2 
  210. from the runstring <fv cypher1.c cypher2.c>
  211.  
  212.  
  213. FSTAT.C - LISTING #6
  214.  
  215. Descriptive  statistics is the name of the game here and as  with 
  216. any statistical evaluation, one must be brutally honest (at least 
  217. with oneself) to draw an objective conclusion. The entire file is 
  218. read,  16Kbytes at a time. As we read, the occurrences of each of 
  219. the 256 tokens is accumulated and we obtain the sum of all  bytes 
  220. as well as the min and max token occurrences.  The sum is divided 
  221. by  the total characters to obtain the mean,  the max becomes the 
  222. mode  and the range is the difference between min and  max.  Next 
  223. the  256  byte array is copied to a second array  and  sorted  to 
  224. obtain the median.
  225.  
  226. With   all  calculations  completed,   the  numerical  values  of 
  227. occurrences  are displayed in a 16 X 16 display  for  evaluation. 
  228. The  statistical  characteristics are displayed and  the  program 
  229. pauses  to  await some keyboard entry to display  the  histogram. 
  230. Depressing  the space bar prints a scaled horizontal histogram of 
  231. 16 groups (0-15, 16-31, . . ., 241-256).
  232.  
  233. The ideal random file (which is what we'd like to see) would have 
  234. the following characteristics:
  235.  
  236.      mean      127.5
  237.      mode      not critical
  238.      range     < 20% of the total bytes divided by 256
  239.      median    at midpoint of range
  240.  
  241.      histogram reasonably flat
  242.  
  243. Remember I said ideal !  This is where judgement and self honesty 
  244. come  into  play.  A  sequential file will  display  these  ideal 
  245. characteristics as well as a true random file.  Also,  files that 
  246. look  too  good statistically should be just as suspect as  those 
  247. that don't. Figure 3 is the output produced by this article as is 
  248. and Figure 4 when its encrypted with the runstring
  249.  
  250.     cypher crypt-tb.art new frederick -1 angelo -2 scacchitti -3
  251.  
  252. In   all  fairness, I  must  state  that  other  possibly  better 
  253. statistical  methods  are better for  determining  randomness.  I 
  254. opted  to use descriptive statistic because they are more  easily 
  255. understood and implemented.
  256.  
  257.  
  258. MAKEF.C - LISTING #7
  259.  
  260. A simple enough utility but an absolutely necessity if we are  to 
  261. evaluate  encryption schemes.  A filename of n 256 byte blocks is 
  262. created and if a value between 0 and 255 is passed the file  will 
  263. be  filled  with  this value.  If no value (or one that  is  non-
  264. numeric) is passed, each block contains a sequential count from 0 
  265. to 255.  An added benefit to this program is its ability to clean 
  266. a disk.  The user simply creates a file the size of the remaining 
  267. disk  space  and then erases it.  This results in all  free  disk 
  268. space being set as the user defined.
  269.  
  270.  
  271. SP.C - LISTING #8
  272.  
  273. Along  with the fstat utility this one confirms or  denys  (maybe 
  274. even  questions) the statistical data we received.  A brute force 
  275. search  method is used to find matching character strings in  the 
  276. file.  By default,  the search starts at the first character  and 
  277. searches the first 128 bytes for a match of 4 or more characters. 
  278. If  the  match depth exceeds the block size it is  searching  the 
  279. program  will return to CP/M after displaying the match data.  If 
  280. not it will continue in its search. Block size to search, minimum 
  281. depth  of  comparison  and  starting  point  in  the  buffer  may 
  282. optionally be changed in the runstring. 
  283.  
  284. Also  if  an  additional argument is passed ( one more  than  the 
  285. three mentioned) the software converts the data in the buffer  to 
  286. delta-form.  That is,  element[n] = element[n] - element[n+1] for 
  287. all data in the buffer.  After the conversion is made the  search 
  288. scheme  continues as before.  This feature allows us to  evaluate 
  289. the file for some mathematical sequence.
  290.  
  291. One drawback to this program as it stands is the limiting  factor 
  292. of the buffer size.  No attempt is made to search beyond it. This 
  293. shouldn't matter for most text files.
  294.  
  295.  
  296. SMALL C, CP/M, AND MISCELLANEOUS
  297.  
  298. chkkbd() is a function which enables us to stop display (program) 
  299. activity  if Control-S is depressed.  Following with a  Control-C 
  300. causes  a  return to CP/M and any other character will allow  the 
  301. program to continue. This function calls a bdos() function so the 
  302. user  may have to modify this for other  operating  systems.  The 
  303. getchx()  function  is a non-echoing version of  getchar()  which 
  304. uses BDOS function 6. getchar() may be substituted for getchx().
  305.  
  306. calloc(), malloc() and cfree() functions are used for the dynamic 
  307. allocation and deallocation of memory. My allocation/deallocation 
  308. scheme  is  of the simple variety where the programmer  must  pay 
  309. heed to order or pay the consequences.  The source code contained 
  310. here should work with most implementations of these functions.
  311.  
  312. Printer  output may be obtained from any of the programs by using 
  313. the  CP/M  Control  P function.  It was the  simplest  method  to 
  314. implement.
  315.  
  316. Math  functions  (especially  floating point) are  difficult  for 
  317. Small-C.  There  are several routines in the fstat.c source  that 
  318. perform the necessary long and fractional calculations.  It's not 
  319. necessary  to  change these however,  if your  compiler  supports 
  320. floats and longs, have at it.
  321.  
  322. Each program will display the usage if entered without the proper 
  323. number of arguments in the run string.  Also, since most software 
  324. users  begin  to feel uncomfortable when their  computer  is  off 
  325. somewhere  performing exotic calculations,  each program displays 
  326. status to the screen thus putting these fears at rest.  
  327.  
  328.  
  329. CYPHER BENCHMARKS
  330.  
  331. My version, written in Small C, is generic enough to adapt to any 
  332. C  compiler.  Running   on  a  4 Mhz Z80 based  CP/M  system,  it 
  333. benchmarks  at less than 1K/sec for file I/O,  16K/sec  for  file 
  334. transposition  and  approximately 4K/sec per key for  encryption. 
  335. Key  encryption is difficult to benchmark since it  includes  the 
  336. time  to generate the prime length key which varies from 1009  to 
  337. 1999 characters in length.
  338.  
  339.  
  340. AND FINALLY
  341.  
  342. These tools should be employed with a measure of common sense.  A 
  343. strong  cypher  is  only indicated when  both  statistically  and 
  344. pattern-whise  indicated.  (And it doesn't hurt to view the  file 
  345. either) My intent in developing these utilities was to enable the 
  346. cryptographer-programmer  a means to evaluate the strength of  an  
  347. encryption  scheme  as  well as the  resistance  of   schemes  to 
  348. "cracking".  However  (like  most  tools) these can be  used  for UP - Version  %s\n", VERSION);
  349.     printf("Copies all files which haven't been previously copied.\n");
  350.     printf("-----------------------------------------------------\n");
  351.     printf("Copyright 1986 - Cogar Computer Services Pty. Ltd.\n");
  352.     printf("All rights reserved.\n\n");
  353. }
  354. /*------------FINISH OF BACKUP-------------------------------------*/("\nThere are no files on this disk.