/* Program: CHDIR Author: Richard Conn Version: 1.0 Date: 22 Aug 82 Previous Versions: None Note: This Program Must Be Compiled with NOBOOT or modified manually so that the Stack is not placed within the CCP Note: After initially compiled, this program should be first run from a system user number with the /S option to set the system password (initially garbage) and the basic directory names */ #define ver 10 /* Version Number */ #define defname "CHDIR.COM" /* Default File Name */ #define dirmax 64 /* Maximum Number of Directories Allowed */ #define syspass "chdir" /* Password for Access to Change Capability */ #define sysuser 10 /* Lowest System User Area */ #define tryent 1 /* Number of Tries to Enter System Area */ #define tryset 3 /* Number of Tries to Enter Setup Mode */ #define exitcmd "" /* Command to Execute on Password Exit */ /* CHDIR is a program which is used to impose a logical directory structure onto the CP/M or CP/ZM Operating Systems. CHDIR performs three functions: 1) CHDIR allows the user to enter one of the defined directories; this form of the CHDIR command is CHDIR dirname where 'dirname' is the name of the directory (up to 8 characters) 2) CHDIR allows the user to define a new directory on the fly; this form of the command is CHDIR dirname du where 'dirname' is the name of the directory (up to 8 characters) and 'du' is the disk and user number the name applies to Along the same lines, the CHDIR Setup option allows the user to define or redefine a number of directories without invoking CHDIR a number of times; this command is of the form CHDIR /SETUP 3) CHDIR displays the names of the known directories to the user; this form of the command is CHDIR /DISPLAY */ /* Global Definitions and Variables */ char spass[21]; /* Buffer for System Password After Init */ char pass[21]; /* Password is Global for Safety */ char directory[dirmax][9]; /* DIRMAX Directories of 8 Chars + NULL Each */ char dirdisk[dirmax]; /* DIRMAX Directory Disks */ int dirun[dirmax]; /* DIRMAX Directory User Numbers */ unsigned ccp; /* Address of CCP */ /* Main Program */ main(argc,argv) int argc; char **argv; { unsigned *bdptr; bdptr = 6; /* Pt to Location 6 for BDOS Location */ ccp = (((*bdptr/256)-8)*256) + 3; /* Restart Location Within CCP */ printf("CHDIR, Version %d.%d",ver/10,ver%10); switch (argc) { case 2 : if (*argv[1] == '/') option(argv[1]); else chdir(argv[1]); break; case 3 : set(argv[1], argv[2]); break; default : help(); break; } } /* Option Processor */ option(ostr) char *ostr; { char *tstr; tstr = ostr; /* assign temp ptr */ printf(" -- Option: "); switch (*++tstr) { case 'D' : printf("Display Directory Names"); display(0); break; case 'S' : printf("Setup of Directory Names"); setup(); break; default : printf("Help"); help(); break; } } /* Help Message */ help() { printf("\n\tCHDIR Program Help Information\n"); printf("\nCHDIR is a program used to impose a named directory"); printf("\nstructure onto a CP/M or CP/ZM Operating System. This"); printf("\nallows the user to select directories (disk and user)"); printf("\nby name (logically) rather than by letter/number."); printf("\n"); printf("\nThe forms of this command are --"); printf("\n\tCHDIR dirname\t<-- select directory"); printf("\n\tCHDIR dirname du\t<-- name directory for disk d user u"); printf("\n\tCHDIR /DISPLAY\t<-- display directory assignments"); printf("\n\tCHDIR /SET\t<-- define several directories"); printf("\n\tCHDIR //\t<-- print HELP information\n"); } /* Change Directory to Name Specified */ chdir(dirname) char *dirname; { int dir, index; unsigned udflag; index = -1; for (dir=0; dir < dirmax; dir++) if (strcmp(directory[dir],dirname) == 0) index = dir; if (index == -1) { printf("\nError -- Can't Find Directory Name"); display(0); return(-1); } if (dirun[index] >= sysuser) password(tryent); /* Require PW System */ udflag = dirun[index] << 4; /* Implant the User Number */ udflag |= dirdisk[index] - 'A'; /* Implant the Disk Number */ call(ccp,0,0,udflag,0); /* Reenter the CCP */ } /* Convert String to Integer */ tonum(str) char *str; { int value, digit; char *tstr; tstr = str; value = 0; while (*tstr != '\0') { digit = *tstr++ - '0'; /* Convert to binary */ if ((digit < 0) || (digit > 9)) return(-1); /* Error */ value = value*10 + digit; } return(value); } /* Display Directory Names and Definitions */ display(flag) int flag; /* If flag==0, only display system files if in system dir */ { int count, dir, user; user = bdos(32,0xff); /* Get current user number */ printf("\nDefined Directory Names --"); count = 0; for (dir = 0; dir < dirmax; dir++) { if ((directory[dir][0] != '\0') && ((user >= sysuser) || (flag != 0) || (dirun[dir] < sysuser))) { if (count%4 == 0) printf("\n"); printf("\t%c%d: %s",dirdisk[dir],dirun[dir], directory[dir]); } if (directory[dir][0] != '\0') count++; } printf("\n%d Directory Names Defined, Space Left for %d More Names\n", count, dirmax-count); disp2(); } /* Display Current Directory Assignment */ disp2() { int un, defined, dir; char disk; printf("\nCurrent Directory --"); un = bdos(32,0xff); /* Get current user number */ disk = bdos(25,0) + 'A'; /* Get current disk letter */ defined = 0; /* Directory Not Defined */ for (dir=0; dir < dirmax; dir++) if ((dirdisk[dir] == disk) && (dirun[dir] == un)) { printf("\t%c%d: %s",disk,un,directory[dir]); defined = 1; /* Directory Defined */ } if (defined == 0) printf(" Not Defined by Name"); printf("\n"); } /* Set up Mnemonic Names */ setup() { char cmd, fname[40]; int i,j,fd; unsigned base; printf("\nCHDIR Setup Subsystem"); password(tryset); /* Ask for password */ do { printf("\nSetup Command (? for Help)? "); cmd = toupper(getchar()); /* Get Response */ switch (cmd) { case 'D' : printf("\nSystem Password is %s",spass); display(1); break; case 'I' : initdir(); break; case 'N' : printf("\nSystem User Areas start at %d", sysuser); while (setdir() == 0); break; case 'P' : printf("\nNew System Password? "); dots(20); scanf("%s",spass); break; case 'Q' : printf("\tVerify Abort (Y/N)? "); if (toupper(getchar()) == 'Y') return(-1); break; case 'S' : sort(); printf("\nSort Complete"); break; case 'X' : break; default : sethlp(); break; } } while (cmd != 'X'); printf("\tWrite New File (Y/N)? "); if (toupper(getchar()) != 'Y') return(-1); printf("\nName of File (RETURN = %s)? ",defname); dots(12); scanf("%s",fname); strcap(fname); /* Input and Capitalize File Name */ if (strlen(fname) == 0) strcpy(fname,defname); /* Set FN if none */ if (strscan(fname) == 0) strcat(fname,".COM"); /* Make type COM */ writepgm(fname); /* Write Program to Disk */ } /* Set Mnemonic Name for a Directory */ setdir() { int i, un, repl, dir; char disk, name[20]; printf("\n\tDisk Letter and User (RETURN=Done or A-P 0-15, like "); printf("A10)? "); scanf("%s",name); /* Get response */ if (strlen(name) == 0) return(-1); /* Done */ disk = toupper(name[0]); /* Get disk letter */ if ((disk < 'A') || (disk > 'P')) { /* disk is out of range */ printf("\n\tInvalid Disk Letter"); return(0); } if ((un = tonum(name+1)) == -1) /* RETURN was specified */ return(-1); if ((un < 0) || (un > 15)) { /* User Number is Out of Range */ printf("\n\tInvalid User Number"); return(0); } do { printf("\tDirectory Name (RETURN = Delete Old Name)? "); dots(8); scanf("%s",name); strcap(name); /* Get and Capitalize Name */ if (strlen(name) > 8) printf("\t\tDirectory Name is too Long -- Reenter\n"); } while (strlen(name) > 8); repl = 0; /* No Replacement */ for (dir=0; dir < dirmax; dir++) if ((dirdisk[dir] == disk) && (dirun[dir] == un)) { repl = dir; /* Replacement */ directory[dir][0] = '\0'; /* Null Out Old Name */ } if (repl == 0) { repl = finddir(); /* Search for Empty Directory Name */ if (repl == -1) { printf("\nError -- Directory Name Buffer Full"); return(-1); } } dirdisk[repl] = '\0'; dirun[repl] = 0; if (strlen(name) != 0) { dirdisk[repl] = disk; /* Set Disk Name */ dirun[repl] = un; /* Set User Number */ strcat(directory[repl],name); /* Make entry in array */ return(0); /* Continue Flag */ } printf("\n\t\tDirectory Name for %c%2d: Deleted",disk,un); return(0); /* Continue Flag */ } /* Initialize directory */ initdir() { int i; char ans; printf("\tVerify Initialization (Y/N)? "); if (toupper(getchar()) != 'Y') { printf("\nInitialization Aborted"); return(-1); } strcpy(spass,syspass); /* Init System Password */ for (i=0; i 'P')) { printf("\nError -- Invalid Disk Letter (not A-P)"); return(-1); } un = tonum(*++dutemp); if ((un < 0) || (un > 31)) { printf("\nError -- Invalid User Number (not 0-31)"); return(-1); } if (scandir(dirname) == -1) { printf("\nError -- Duplicate Directory Name"); return(-1); } if (un >= sysuser) password(tryset); /* Ask for Password */ dir = finddir(); /* Find available directory entry */ if (dir == -1) { printf("\nError -- Directory Buffer Full"); return(-1); } strcpy(directory[dir],dirname); /* Set Name */ dirdisk[dir] = disk; dirun[dir] = un; writepgm(defname); /* Write Program to Disk */ return(0); } /* Write Program to Disk Under Passed Name */ writepgm(fname) char *fname; { int fd; unsigned cend; printf("\nSorting Directory by Disk and User Number"); sort(); printf("\nWriting File %s to Disk ...",fname); fd = creat(fname); /* Delete old file and open new one */ if (fd == -1) { printf("\nError -- Can't Create File %s",fname); return(-1); } cend = codend()/128+(dirmax*12)/128; /* Determine size of code */ write(fd,0x100,cend); /* Write file to disk */ close(fd); /* Close file -- done */ printf(" File %s Written to Disk\n",fname); } /* Ask for password n times and abort if not matched by then */ password(n) int n; { int i; if (bdos(32,0xff) >= sysuser) return(0); /* Pass if system */ printf("\n\n** System Password Required for Access/Permission **"); for (i=0; i 20) { printf("\n** Violation Attempt **"); exit(-1); } if (strcmp(spass,pass) == 0) { printf("\t** Access Granted **"); return(0); } printf("\tInvalid Password Given"); } printf("\n\t** Access Denied **"); if (strlen(exitcmd) == 0) exit(-1); /* Abort to OS if no command */ exec(exitcmd); /* Execute Command on Exit */ } /* Sort Directory by Disk and User Number */ sort() { int i, j; for (i=0; i J */ compare(i,j) int i,j; { if (dirdisk[i] < dirdisk[j]) return(0); /* J > I */ if (dirdisk[i] > dirdisk[j]) { /* I>J so Swap */ swap(i,j); return(0); } if (dirun[i] > dirun[j]) swap(i,j); /* I>J so Swap */ return(0); } /* Swap Directory Entries I and J */ swap(i,j) int i,j; { char disk, name; int un, k; disk = dirdisk[i]; dirdisk[i] = dirdisk[j]; dirdisk[j] = disk; un = dirun[i]; dirun[i] = dirun[j]; dirun[j] = un; for (k=0; k<9; k++) { name = directory[i][k]; directory[i][k] = directory[j][k]; directory[j][k] = name; } } /* Find an Empty Directory Entry -- Return -1 if Not Found */ finddir() { int dir; for (dir=0; dir < dirmax; dir++) if (directory[dir][0] == '\0') return(dir); return(-1); } /* Scan Directory Name Buffer for Duplicate Name */ scandir(name) char *name; { int dir; for (dir=0; dir < dirmax; dir++) if (strcmp(directory[dir],name) == 0) return(-1); return(0); } /* Capitalize String */ strcap(str) char *str; { char *tstr; tstr = str; while (*tstr != '\0') { *tstr = toupper(*tstr); tstr++; } } /* Help File for Interactive Setup Commands */ sethlp() { printf("\nCHDIR Setup Subsystem Command Summary"); printf("\n\tD -- Display Currently-Defined Directory Names"); printf("\n\tI -- Initialize and Clear All Directory Names"); printf("\n\tN -- Create a New Directory Name"); printf("\n\tP -- Set System Password"); printf("\n\tQ -- Quit without Changing Program on Disk"); printf("\n\tS -- Sort Directory by Disk and User Number"); printf("\n\tX -- Exit and Update Program on Disk"); } /* Print num dots followed by num on screen */ dots(num) int num; { int i; for (i=0; i