home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / dirutl / chdir.lbr / CHDIR10.CZ / CHDIR10.C
Text File  |  1987-12-26  |  14KB  |  506 lines

  1. /*
  2.     Program:  CHDIR
  3.     Author:  Richard Conn
  4.     Version:  1.0
  5.     Date:  22 Aug 82
  6.     Previous Versions:  None
  7.     Note:  This Program Must Be Compiled with NOBOOT or modified
  8.         manually so that the Stack is not placed within the CCP
  9.     Note:  After initially compiled, this program should be
  10.         first run from a system user number with the /S
  11.         option to set the system password (initially garbage)
  12.         and the basic directory names
  13.  
  14. */
  15. #define    ver    10        /* Version Number */
  16. #define    defname    "CHDIR.COM"    /* Default File Name */
  17. #define    dirmax    64        /* Maximum Number of Directories Allowed */
  18. #define    syspass    "chdir"        /* Password for Access to Change Capability */
  19. #define    sysuser    10        /* Lowest System User Area */
  20. #define    tryent    1        /* Number of Tries to Enter System Area */
  21. #define    tryset    3        /* Number of Tries to Enter Setup Mode */
  22. #define    exitcmd    ""        /* Command to Execute on Password Exit */
  23.  
  24. /*
  25.  
  26.     CHDIR is a program which is used to impose a logical directory
  27. structure onto the CP/M or CP/ZM Operating Systems.  CHDIR performs
  28. three functions:
  29.  
  30.         1) CHDIR allows the user to enter one of the defined
  31. directories; this form of the CHDIR command is
  32.             CHDIR dirname
  33. where 'dirname' is the name of the directory (up to 8 characters)
  34.         2) CHDIR allows the user to define a new directory on
  35. the fly; this form of the command is
  36.             CHDIR dirname du
  37. where 'dirname' is the name of the directory (up to 8 characters) and
  38. 'du' is the disk and user number the name applies to
  39.            Along the same lines, the CHDIR Setup option allows
  40. the user to define or redefine a number of directories without invoking
  41. CHDIR a number of times; this command is of the form
  42.             CHDIR /SETUP
  43.         3) CHDIR displays the names of the known directories to
  44. the user; this form of the command is
  45.             CHDIR /DISPLAY
  46.  
  47. */
  48.  
  49. /*  Global Definitions and Variables  */
  50. char spass[21];  /* Buffer for System Password After Init */
  51. char pass[21];  /* Password is Global for Safety */
  52. char directory[dirmax][9];  /* DIRMAX Directories of 8 Chars + NULL Each */
  53. char dirdisk[dirmax];  /* DIRMAX Directory Disks */
  54. int dirun[dirmax];  /* DIRMAX Directory User Numbers */
  55. unsigned ccp;  /* Address of CCP */
  56.  
  57. /*  Main Program  */
  58. main(argc,argv)
  59. int argc;
  60. char **argv;
  61. {
  62.     unsigned *bdptr;
  63.  
  64.     bdptr = 6;  /* Pt to Location 6 for BDOS Location */
  65.     ccp = (((*bdptr/256)-8)*256) + 3;  /* Restart Location Within CCP */
  66.  
  67.     printf("CHDIR, Version %d.%d",ver/10,ver%10);
  68.     switch (argc) {
  69.         case 2 : if (*argv[1] == '/') option(argv[1]);
  70.                 else chdir(argv[1]);
  71.              break;
  72.         case 3 : set(argv[1], argv[2]); break;
  73.         default : help(); break;
  74.         }
  75. }
  76.  
  77. /*  Option Processor  */
  78. option(ostr)
  79. char *ostr;
  80. {
  81.     char *tstr;
  82.  
  83.     tstr = ostr;  /* assign temp ptr */
  84.     printf("  -- Option: ");
  85.     switch (*++tstr) {
  86.         case 'D' : printf("Display Directory Names");
  87.                display(0); break;
  88.         case 'S' : printf("Setup of Directory Names");
  89.                setup(); break;
  90.         default  : printf("Help");
  91.                help(); break;
  92.         }
  93. }
  94.  
  95. /*  Help Message  */
  96. help()
  97. {
  98.     printf("\n\tCHDIR Program Help Information\n");
  99.  
  100.     printf("\nCHDIR is a program used to impose a named directory");
  101.     printf("\nstructure onto a CP/M or CP/ZM Operating System.  This");
  102.     printf("\nallows the user to select directories (disk and user)");
  103.     printf("\nby name (logically) rather than by letter/number.");
  104.     printf("\n");
  105.  
  106.     printf("\nThe forms of this command are --");
  107.  
  108.     printf("\n\tCHDIR dirname\t<-- select directory");
  109.  
  110.     printf("\n\tCHDIR dirname du\t<-- name directory for disk d user u");
  111.  
  112.     printf("\n\tCHDIR /DISPLAY\t<-- display directory assignments");
  113.  
  114.     printf("\n\tCHDIR /SET\t<-- define several directories");
  115.  
  116.     printf("\n\tCHDIR //\t<-- print HELP information\n");
  117. }
  118.  
  119. /*  Change Directory to Name Specified  */
  120. chdir(dirname)
  121. char *dirname;
  122. {
  123.     int dir, index;
  124.     unsigned udflag;
  125.  
  126.     index = -1;
  127.     for (dir=0; dir < dirmax; dir++)
  128.         if (strcmp(directory[dir],dirname) == 0) index = dir;
  129.     if (index == -1) {
  130.         printf("\nError -- Can't Find Directory Name");
  131.         display(0);
  132.         return(-1);
  133.         }
  134.     if (dirun[index] >= sysuser) password(tryent);  /* Require PW System */
  135.     udflag = dirun[index] << 4;  /*  Implant the User Number  */
  136.     udflag |= dirdisk[index] - 'A';  /*  Implant the Disk Number  */
  137.     call(ccp,0,0,udflag,0);  /*  Reenter the CCP  */
  138. }
  139.  
  140. /*  Convert String to Integer  */
  141. tonum(str)
  142. char *str;
  143. {
  144.     int value, digit;
  145.     char *tstr;
  146.  
  147.     tstr = str;
  148.     value = 0;
  149.     while (*tstr != '\0') {
  150.         digit = *tstr++ - '0';  /* Convert to binary */
  151.         if ((digit < 0) || (digit > 9)) return(-1);  /*  Error  */
  152.         value = value*10 + digit;
  153.         }
  154.     return(value);
  155. }
  156.  
  157. /*  Display Directory Names and Definitions  */
  158. display(flag)
  159. int flag;  /* If flag==0, only display system files if in system dir */
  160. {
  161.     int count, dir, user;
  162.  
  163.     user = bdos(32,0xff);  /* Get current user number */
  164.     printf("\nDefined Directory Names --");
  165.     count = 0;
  166.     for (dir = 0; dir < dirmax; dir++) {
  167.         if ((directory[dir][0] != '\0') &&
  168.         ((user >= sysuser) || (flag != 0) || (dirun[dir] < sysuser))) {
  169.             if (count%4 == 0) printf("\n");
  170.             printf("\t%c%d: %s",dirdisk[dir],dirun[dir],
  171.                 directory[dir]);
  172.             }
  173.         if (directory[dir][0] != '\0') count++;
  174.         }
  175.     printf("\n%d Directory Names Defined, Space Left for %d More Names\n",
  176.         count, dirmax-count);
  177.     disp2();
  178. }
  179.  
  180. /*  Display Current Directory Assignment  */
  181. disp2()
  182. {
  183.     int un, defined, dir;
  184.     char disk;
  185.  
  186.     printf("\nCurrent Directory --");
  187.     un = bdos(32,0xff);  /* Get current user number */
  188.     disk = bdos(25,0) + 'A';  /* Get current disk letter */
  189.     defined = 0;  /* Directory Not Defined */
  190.     for (dir=0; dir < dirmax; dir++)
  191.         if ((dirdisk[dir] == disk) && (dirun[dir] == un)) {
  192.             printf("\t%c%d: %s",disk,un,directory[dir]);
  193.             defined = 1;  /* Directory Defined */
  194.             }
  195.     if (defined == 0) printf(" Not Defined by Name");
  196.     printf("\n");
  197. }
  198.  
  199. /*  Set up Mnemonic Names  */
  200. setup()
  201. {
  202.     char cmd, fname[40];
  203.     int i,j,fd;
  204.     unsigned base;
  205.  
  206.     printf("\nCHDIR Setup Subsystem");
  207.     password(tryset);  /* Ask for password */
  208.     do {
  209.         printf("\nSetup Command (? for Help)? ");
  210.         cmd = toupper(getchar());  /* Get Response */
  211.         switch (cmd) {
  212.             case 'D' : printf("\nSystem Password is %s",spass);
  213.                    display(1); break;
  214.             case 'I' : initdir(); break;
  215.             case 'N' : printf("\nSystem User Areas start at %d",
  216.                     sysuser);
  217.                    while (setdir() == 0); break;
  218.             case 'P' : printf("\nNew System Password? ");
  219.                    dots(20);
  220.                    scanf("%s",spass);
  221.                    break;
  222.             case 'Q' : printf("\tVerify Abort (Y/N)? ");
  223.                     if (toupper(getchar()) == 'Y')
  224.                         return(-1);
  225.                     break;
  226.             case 'S' : sort(); printf("\nSort Complete"); break;
  227.             case 'X' : break;
  228.             default  : sethlp(); break;
  229.             }
  230.     } while (cmd != 'X');
  231.     printf("\tWrite New File (Y/N)? ");
  232.     if (toupper(getchar()) != 'Y') return(-1);
  233.     printf("\nName of File (RETURN = %s)? ",defname);
  234.     dots(12);
  235.     scanf("%s",fname); strcap(fname);  /* Input and Capitalize File Name */
  236.     if (strlen(fname) == 0) strcpy(fname,defname);  /* Set FN if none */
  237.     if (strscan(fname) == 0) strcat(fname,".COM");  /* Make type COM */
  238.     writepgm(fname);  /* Write Program to Disk */
  239. }
  240.  
  241. /*  Set Mnemonic Name for a Directory  */
  242. setdir()
  243. {
  244.     int i, un, repl, dir;
  245.     char disk, name[20];
  246.  
  247.     printf("\n\tDisk Letter and User (RETURN=Done or A-P 0-15, like ");
  248.         printf("A10)? ");
  249.     scanf("%s",name);  /* Get response */
  250.     if (strlen(name) == 0) return(-1);  /* Done */
  251.     disk = toupper(name[0]);  /* Get disk letter */
  252.     if ((disk < 'A') || (disk > 'P')) { /* disk is out of range */
  253.         printf("\n\tInvalid Disk Letter");
  254.         return(0);
  255.         }
  256.     if ((un = tonum(name+1)) == -1) /* RETURN was specified */
  257.         return(-1);
  258.     if ((un < 0) || (un > 15)) {  /* User Number is Out of Range */
  259.         printf("\n\tInvalid User Number");
  260.         return(0);
  261.         }
  262.     do {
  263.         printf("\tDirectory Name (RETURN = Delete Old Name)? ");
  264.         dots(8);
  265.         scanf("%s",name); strcap(name);  /* Get and Capitalize Name */
  266.         if (strlen(name) > 8)
  267.             printf("\t\tDirectory Name is too Long -- Reenter\n");
  268.     } while (strlen(name) > 8);
  269.     repl = 0;  /* No Replacement */
  270.     for (dir=0; dir < dirmax; dir++)
  271.         if ((dirdisk[dir] == disk) && (dirun[dir] == un)) {
  272.             repl = dir;  /* Replacement */
  273.             directory[dir][0] = '\0';  /* Null Out Old Name */
  274.             }
  275.     if (repl == 0) {
  276.         repl = finddir();  /* Search for Empty Directory Name */
  277.         if (repl == -1) {
  278.             printf("\nError -- Directory Name Buffer Full");
  279.             return(-1);
  280.             }
  281.         }
  282.     dirdisk[repl] = '\0';
  283.     dirun[repl] = 0;
  284.     if (strlen(name) != 0) {
  285.         dirdisk[repl] = disk;  /* Set Disk Name */
  286.         dirun[repl] = un;  /* Set User Number */
  287.         strcat(directory[repl],name);  /* Make entry in array */
  288.         return(0);  /* Continue Flag */
  289.         }
  290.     printf("\n\t\tDirectory Name for %c%2d: Deleted",disk,un);
  291.     return(0);  /* Continue Flag */
  292. }
  293.  
  294. /*  Initialize directory  */
  295. initdir()
  296. {
  297.     int i;
  298.     char ans;
  299.  
  300.     printf("\tVerify Initialization (Y/N)? ");
  301.     if (toupper(getchar()) != 'Y') {
  302.         printf("\nInitialization Aborted");
  303.         return(-1);
  304.         }
  305.     strcpy(spass,syspass);  /* Init System Password */
  306.     for (i=0; i<dirmax; i++) {
  307.         directory[i][0] = '\0';
  308.         dirdisk[i] = '\0';
  309.         dirun[i] = 0;
  310.         }
  311.     printf("\nAll Directory Names Cleared");
  312. }
  313.  
  314. /*  Set Directory Name for specified disk/user number  */
  315. set(dirname,duser)
  316. char *dirname, *duser;
  317. {
  318.     char disk, *dutemp;
  319.     int un, dir;
  320.  
  321.     dutemp = duser;
  322.     disk = *duser;
  323.     if ((disk < 'A') || (disk > 'P')) {
  324.         printf("\nError -- Invalid Disk Letter (not A-P)");
  325.         return(-1);
  326.         }
  327.     un = tonum(*++dutemp);
  328.     if ((un < 0) || (un > 31)) {
  329.         printf("\nError -- Invalid User Number (not 0-31)");
  330.         return(-1);
  331.         }
  332.     if (scandir(dirname) == -1) {
  333.         printf("\nError -- Duplicate Directory Name");
  334.         return(-1);
  335.         }
  336.     if (un >= sysuser) password(tryset);  /* Ask for Password */
  337.     dir = finddir();  /* Find available directory entry */
  338.     if (dir == -1) {
  339.         printf("\nError -- Directory Buffer Full");
  340.         return(-1);
  341.         }
  342.     strcpy(directory[dir],dirname);  /* Set Name */
  343.     dirdisk[dir] = disk;
  344.     dirun[dir] = un;
  345.     writepgm(defname);  /* Write Program to Disk */
  346.     return(0);
  347. }
  348.  
  349. /*  Write Program to Disk Under Passed Name  */
  350. writepgm(fname)
  351. char *fname;
  352. {
  353.     int fd;
  354.     unsigned cend;
  355.  
  356.     printf("\nSorting Directory by Disk and User Number");
  357.     sort();
  358.     printf("\nWriting File %s to Disk ...",fname);
  359.     fd = creat(fname);  /* Delete old file and open new one */
  360.     if (fd == -1) {
  361.         printf("\nError -- Can't Create File %s",fname);
  362.         return(-1);
  363.         }
  364.     cend = codend()/128+(dirmax*12)/128;  /* Determine size of code */
  365.     write(fd,0x100,cend);  /* Write file to disk */
  366.     close(fd);  /* Close file -- done */
  367.     printf(" File %s Written to Disk\n",fname);
  368. }
  369.  
  370. /*  Ask for password n times and abort if not matched by then  */
  371. password(n)
  372. int n;
  373. {
  374.     int i;
  375.  
  376.     if (bdos(32,0xff) >= sysuser) return(0);  /* Pass if system */
  377.     printf("\n\n** System Password Required for Access/Permission **");
  378.     for (i=0; i<n; i++) {
  379.         printf("\n\tSystem Password? ");
  380.         dots(20);
  381.         scanf("%s",pass);
  382.         if (strlen(pass) > 20) {
  383.             printf("\n** Violation Attempt **");
  384.             exit(-1);
  385.             }
  386.         if (strcmp(spass,pass) == 0) {
  387.             printf("\t** Access Granted **");
  388.             return(0);
  389.             }
  390.         printf("\tInvalid Password Given");
  391.         }
  392.     printf("\n\t** Access Denied **");
  393.     if (strlen(exitcmd) == 0) exit(-1);  /* Abort to OS if no command */
  394.     exec(exitcmd);  /* Execute Command on Exit */
  395. }
  396.  
  397. /*  Sort Directory by Disk and User Number  */
  398. sort()
  399. {
  400.     int i, j;
  401.  
  402.     for (i=0; i<dirmax; i++)
  403.         for (j=i+1; j<dirmax; j++)
  404.             if ((dirdisk[i] != '\0') && (dirdisk[j] != '\0'))
  405.                 compare(i,j);
  406. }
  407.  
  408. /*  Compare Directory Entry I to Directory Entry J and Swap if I > J  */
  409. compare(i,j)
  410. int i,j;
  411. {
  412.     if (dirdisk[i] < dirdisk[j]) return(0);  /* J > I */
  413.     if (dirdisk[i] > dirdisk[j]) {  /* I>J so Swap */
  414.         swap(i,j);
  415.         return(0);
  416.         }
  417.     if (dirun[i] > dirun[j]) swap(i,j);  /* I>J so Swap */
  418.     return(0);
  419. }
  420.  
  421. /*  Swap Directory Entries I and J  */
  422. swap(i,j)
  423. int i,j;
  424. {
  425.     char disk, name;
  426.     int un, k;
  427.  
  428.     disk = dirdisk[i]; dirdisk[i] = dirdisk[j]; dirdisk[j] = disk;
  429.     un = dirun[i]; dirun[i] = dirun[j]; dirun[j] = un;
  430.     for (k=0; k<9; k++) {
  431.         name = directory[i][k];
  432.         directory[i][k] = directory[j][k];
  433.         directory[j][k] = name;
  434.         }
  435. }
  436.  
  437.  
  438. /*  Find an Empty Directory Entry -- Return -1 if Not Found  */
  439. finddir()
  440. {
  441.     int dir;
  442.  
  443.     for (dir=0; dir < dirmax; dir++)
  444.         if (directory[dir][0] == '\0') return(dir);
  445.     return(-1);
  446. }
  447.  
  448. /*  Scan Directory Name Buffer for Duplicate Name */
  449. scandir(name)
  450. char *name;
  451. {
  452.     int dir;
  453.  
  454.     for (dir=0; dir < dirmax; dir++)
  455.         if (strcmp(directory[dir],name) == 0) return(-1);
  456.     return(0);
  457. }
  458.  
  459. /*  Capitalize String  */
  460. strcap(str)
  461. char *str;
  462. {
  463.     char *tstr;
  464.  
  465.     tstr = str;
  466.     while (*tstr != '\0') {
  467.         *tstr = toupper(*tstr);
  468.         tstr++;
  469.         }
  470. }
  471.  
  472. /*  Help File for Interactive Setup Commands  */
  473. sethlp()
  474. {
  475.     printf("\nCHDIR Setup Subsystem Command Summary");
  476.     printf("\n\tD -- Display Currently-Defined Directory Names");
  477.     printf("\n\tI -- Initialize and Clear All Directory Names");
  478.     printf("\n\tN -- Create a New Directory Name");
  479.     printf("\n\tP -- Set System Password");
  480.     printf("\n\tQ -- Quit without Changing Program on Disk");
  481.     printf("\n\tS -- Sort Directory by Disk and User Number");
  482.     printf("\n\tX -- Exit and Update Program on Disk");
  483. }
  484.  
  485. /*  Print num dots followed by num <BS> on screen  */
  486. dots(num)
  487. int num;
  488. {
  489.     int i;
  490.  
  491.     for (i=0; i<num; i++) putchar('.');
  492.     for (i=0; i<num; i++) putchar('\010');
  493. }
  494.  
  495. /*  Scan passed string for a decimal and return zero if not found  */
  496. strscan(str)
  497. char *str;
  498. {
  499.     char *tstr;
  500.  
  501.     tstr = str;  /* pt to first char */
  502.     while (*tstr != '\0')
  503.         if (*tstr++ == '.') return (-1);
  504.     return(0);  /* Didn't find dot */
  505. }
  506.