mirror of
https://github.com/open-simh/simtools.git
synced 2026-02-16 21:00:54 +00:00
897 lines
28 KiB
C
897 lines
28 KiB
C
/* ODS2.C v1.2 Mainline ODS2 program */
|
|
|
|
/*
|
|
This is part of ODS2 written by Paul Nankervis,
|
|
email address: Paulnank@au1.ibm.com
|
|
|
|
ODS2 is distributed freely for all members of the
|
|
VMS community to use. However all derived works
|
|
must maintain comments in their source to acknowledge
|
|
the contibution of the original author.
|
|
|
|
The modules in ODS2 are:-
|
|
|
|
ACCESS.C Routines for accessing ODS2 disks
|
|
CACHE.C Routines for managing memory cache
|
|
DEVICE.C Routines to maintain device information
|
|
DIRECT.C Routines for handling directories
|
|
ODS2.C The mainline program
|
|
PHYVMS.C Routine to perform physical I/O
|
|
RMS.C Routines to handle RMS structures
|
|
VMSTIME.C Routines to handle VMS times
|
|
|
|
On non-VMS platforms PHYVMS.C should be replaced as follows:-
|
|
|
|
OS/2 PHYOS2.C
|
|
Windows 95/NT PHYNT.C
|
|
|
|
For example under OS/2 the program is compiled using the GCC
|
|
compiler with the single command:-
|
|
|
|
gcc -fdollars-in-identifiers ods2.c,rms.c,direct.c,
|
|
access.c,device.c,cache.c,phyos2.c,vmstime.c
|
|
*/
|
|
|
|
/* This version will compile and run using normal VMS I/O by
|
|
defining VMSIO
|
|
*/
|
|
|
|
/* This is the top level set of routines. It is fairly
|
|
simple minded asking the user for a command, doing some
|
|
primitive command parsing, and then calling a set of routines
|
|
to perform whatever function is required (for example COPY).
|
|
Some routines are implemented in different ways to test the
|
|
underlying routines - for example TYPE is implemented without
|
|
a NAM block meaning that it cannot support wildcards...
|
|
(sorry! - could be easily fixed though!)
|
|
*/
|
|
|
|
#define DEBUGx on
|
|
#define VMSIOx on
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "descrip.h"
|
|
#include "ssdef.h"
|
|
|
|
#ifdef VMSIO
|
|
#include <starlet.h>
|
|
#include <rms.h>
|
|
unsigned sys$setddir();
|
|
#else
|
|
#include "rms.h"
|
|
#include "access.h"
|
|
#endif
|
|
|
|
|
|
#define PRINT_ATTR (FAB$M_CR | FAB$M_PRN | FAB$M_FTN)
|
|
|
|
|
|
|
|
/* keycomp: routine to compare parameter to a keyword - case insensitive! */
|
|
|
|
int keycomp(char *param,char *keywrd)
|
|
{
|
|
while (*param != '\0') {
|
|
if (tolower(*param++) != *keywrd++) return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* checkquals: routine to find a qualifer in a list of possible values */
|
|
|
|
int checkquals(char *qualset[],int qualc,char *qualv[])
|
|
{
|
|
int result = 0;
|
|
while (qualc-- > 0) {
|
|
int i = 0;
|
|
while (qualset[i] != NULL) {
|
|
if (keycomp(qualv[qualc],qualset[i])) {
|
|
result |= 1 << i;
|
|
i = -1;
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if (i >= 0) printf("%%ODS2-W-ILLQUAL, Unknown qualifer '%s' ignored\n",qualv[qualc]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/* dir: a directory routine */
|
|
|
|
char *dirquals[] = {"date","file","size",NULL};
|
|
|
|
unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
|
|
int sts,options;
|
|
int filecount = 0;
|
|
struct NAM nam = cc$rms_nam;
|
|
struct FAB fab = cc$rms_fab;
|
|
struct XABDAT dat = cc$rms_xabdat;
|
|
struct XABFHC fhc = cc$rms_xabfhc;
|
|
nam.nam$l_esa = res;
|
|
nam.nam$b_ess = NAM$C_MAXRSS;
|
|
fab.fab$l_nam = &nam;
|
|
fab.fab$l_xab = &dat;
|
|
dat.xab$l_nxt = &fhc;
|
|
fab.fab$l_fna = argv[1];
|
|
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
|
fab.fab$l_dna = "*.*;*";
|
|
fab.fab$b_dns = strlen(fab.fab$l_dna);
|
|
options = checkquals(dirquals,qualc,qualv);
|
|
sts = sys$parse(&fab);
|
|
if (sts & 1) {
|
|
char dir[NAM$C_MAXRSS + 1];
|
|
int namelen;
|
|
int dirlen = 0;
|
|
int dirfiles = 0,dircount = 0;
|
|
int dirblocks = 0,totblocks = 0;
|
|
int printcol = 0;
|
|
#ifdef DEBUG
|
|
res[nam.nam$b_esl] = '\0';
|
|
printf("Parse: %s\n",res);
|
|
#endif
|
|
nam.nam$l_rsa = rsa;
|
|
nam.nam$b_rss = NAM$C_MAXRSS;
|
|
fab.fab$l_fop = FAB$M_NAM;
|
|
while ((sts = sys$search(&fab)) & 1) {
|
|
if (dirlen != nam.nam$b_dev + nam.nam$b_dir ||
|
|
memcmp(rsa,dir,nam.nam$b_dev + nam.nam$b_dir) != 0) {
|
|
if (dirfiles > 0) {
|
|
if (printcol > 0) printf("\n");
|
|
printf("\nTotal of %d file%s",dirfiles,(dirfiles == 1 ? "" : "s"));
|
|
if (options & 4) {
|
|
printf(", %d block%s.\n",dirblocks,(dirblocks == 1 ? "" : "s"));
|
|
} else {
|
|
fputs(".\n",stdout);
|
|
}
|
|
}
|
|
dirlen = nam.nam$b_dev + nam.nam$b_dir;
|
|
memcpy(dir,rsa,dirlen);
|
|
dir[dirlen] = '\0';
|
|
printf("\nDirectory %s\n\n",dir);
|
|
filecount += dirfiles;
|
|
totblocks += dirblocks;
|
|
dircount++;
|
|
dirfiles = 0;
|
|
dirblocks = 0;
|
|
printcol = 0;
|
|
}
|
|
rsa[nam.nam$b_rsl] = '\0';
|
|
namelen = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
|
|
if (options == 0) {
|
|
if (printcol > 0) {
|
|
int newcol = (printcol + 20) / 20 * 20;
|
|
if (newcol + namelen >= 80) {
|
|
fputs("\n",stdout);
|
|
printcol = 0;
|
|
} else {
|
|
printf("%*s",newcol - printcol," ");
|
|
printcol = newcol;
|
|
}
|
|
}
|
|
fputs(rsa + dirlen,stdout);
|
|
printcol += namelen;
|
|
} else {
|
|
if (namelen > 18) {
|
|
printf("%s\n ",rsa + dirlen);
|
|
} else {
|
|
printf("%-19s",rsa + dirlen);
|
|
}
|
|
sts = sys$open(&fab);
|
|
if ((sts & 1) == 0) {
|
|
printf("Open error: %d\n",sts);
|
|
} else {
|
|
sts = sys$close(&fab);
|
|
if (options & 2) {
|
|
char fileid[100];
|
|
sprintf(fileid,"(%d,%d,%d)",
|
|
(nam.nam$b_fid_nmx << 16) | nam.nam$w_fid_num,
|
|
nam.nam$w_fid_seq,nam.nam$b_fid_rvn);
|
|
printf(" %-22s",fileid);
|
|
}
|
|
if (options & 4) {
|
|
unsigned filesize = fhc.xab$l_ebk;
|
|
if (fhc.xab$w_ffb == 0) filesize--;
|
|
printf("%9d",filesize);
|
|
dirblocks += filesize;
|
|
}
|
|
if (options & 1) {
|
|
char tim[24];
|
|
struct dsc$descriptor timdsc;
|
|
timdsc.dsc$w_length = 23;
|
|
timdsc.dsc$a_pointer = tim;
|
|
sts = sys$asctim(0,&timdsc,&dat.xab$q_cdt,0);
|
|
if ((sts & 1) == 0) printf("Asctim error: %d\n",sts);
|
|
tim[23] = '\0';
|
|
printf(" %s",tim);
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
dirfiles++;
|
|
}
|
|
if (sts == RMS$_NMF) sts = 1;
|
|
if (printcol > 0) printf("\n");
|
|
if (dirfiles > 0) {
|
|
printf("\nTotal of %d file%s",dirfiles,(dirfiles == 1 ? "" : "s"));
|
|
if (options & 4) {
|
|
printf(", %d block%s.\n",dirblocks,(dirblocks == 1 ? "" : "s"));
|
|
} else {
|
|
fputs(".\n",stdout);
|
|
}
|
|
filecount += dirfiles;
|
|
totblocks += dirblocks;
|
|
if (dircount > 1) {
|
|
printf("\nGrand total of %d director%s, %d file%s",
|
|
dircount,(dircount == 1 ? "y" : "ies"),
|
|
filecount,(filecount == 1 ? "" : "s"));
|
|
if (options & 4) {
|
|
printf(", %d block%s.\n",totblocks,(totblocks == 1 ? "" : "s"));
|
|
} else {
|
|
fputs(".\n",stdout);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (sts & 1) {
|
|
if (filecount < 1) printf("%%DIRECT-W-NOFILES, no files found\n");
|
|
} else {
|
|
printf("%%DIR-E-ERROR Status: %d\n",sts);
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
|
|
/* copy: a file copy routine */
|
|
|
|
#define MAXREC 32767
|
|
|
|
unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
int sts;
|
|
struct NAM nam = cc$rms_nam;
|
|
struct FAB fab = cc$rms_fab;
|
|
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
|
|
int filecount = 0;
|
|
nam.nam$l_esa = res;
|
|
nam.nam$b_ess = NAM$C_MAXRSS;
|
|
fab.fab$l_nam = &nam;
|
|
fab.fab$l_fna = argv[1];
|
|
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
|
sts = sys$parse(&fab);
|
|
if (sts & 1) {
|
|
nam.nam$l_rsa = rsa;
|
|
nam.nam$b_rss = NAM$C_MAXRSS;
|
|
fab.fab$l_fop = FAB$M_NAM;
|
|
while ((sts = sys$search(&fab)) & 1) {
|
|
sts = sys$open(&fab);
|
|
if ((sts & 1) == 0) {
|
|
printf("%%COPY-F-OPENFAIL, Open error: %d\n",sts);
|
|
perror("-COPY-F-ERR ");
|
|
} else {
|
|
struct RAB rab = cc$rms_rab;
|
|
rab.rab$l_fab = &fab;
|
|
if ((sts = sys$connect(&rab)) & 1) {
|
|
FILE *tof;
|
|
char name[NAM$C_MAXRSS + 1];
|
|
unsigned records = 0;
|
|
{
|
|
char *out = name,*inp = argv[2];
|
|
int dot = 0;
|
|
while (*inp != '\0') {
|
|
if (*inp == '*') {
|
|
inp++;
|
|
if (dot) {
|
|
memcpy(out,nam.nam$l_type + 1,nam.nam$b_type - 1);
|
|
out += nam.nam$b_type - 1;
|
|
} else {
|
|
unsigned length = nam.nam$b_name;
|
|
if (*inp == '\0') length += nam.nam$b_type;
|
|
memcpy(out,nam.nam$l_name,length);
|
|
out += length;
|
|
}
|
|
} else {
|
|
if (*inp == '.') {
|
|
dot = 1;
|
|
} else {
|
|
if (strchr(":]\\/",*inp)) dot = 0;
|
|
}
|
|
*out++ = *inp++;
|
|
}
|
|
}
|
|
*out++ = '\0';
|
|
}
|
|
tof = fopen(name,"w");
|
|
if (tof == NULL) {
|
|
printf("%%COPY-F-OPENOUT, Could not open %s\n",name);
|
|
perror("-COPY-F-ERR ");
|
|
} else {
|
|
char rec[MAXREC + 2];
|
|
filecount++;
|
|
rab.rab$l_ubf = rec;
|
|
rab.rab$w_usz = MAXREC;
|
|
while ((sts = sys$get(&rab)) & 1) {
|
|
unsigned rsz = rab.rab$w_rsz;
|
|
if (fab.fab$b_rat & PRINT_ATTR) rec[rsz++] = '\n';
|
|
if (fwrite(rec,rsz,1,tof) == 1) {
|
|
records++;
|
|
} else {
|
|
printf("%%COPY-F- fwrite error!!\n");
|
|
perror("-COPY-F-ERR ");
|
|
break;
|
|
}
|
|
}
|
|
if (fclose(tof)) {
|
|
printf("%%COPY-F- fclose error!!\n");
|
|
perror("-COPY-F-ERR ");
|
|
}
|
|
}
|
|
sys$disconnect(&rab);
|
|
if (sts == RMS$_EOF) {
|
|
rsa[nam.nam$b_rsl] = '\0';
|
|
printf("%%COPY-S-COPIED, %s copied to %s (%d record%s)\n",
|
|
rsa,name,records,(records == 1 ? "" : "s"));
|
|
sts = 1;
|
|
}
|
|
}
|
|
sys$close(&fab);
|
|
}
|
|
}
|
|
if (sts == RMS$_NMF) sts = 1;
|
|
}
|
|
if (sts & 1) {
|
|
if (filecount > 0) printf("%%COPY-S-NEWFILES, %d file%s created\n",
|
|
filecount,(filecount == 1 ? "" : "s"));
|
|
} else {
|
|
printf("%%COPY-F-ERROR Status: %d\n",sts);
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
|
|
/* diff: a simple file difference routine */
|
|
|
|
unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
int sts;
|
|
struct FAB fab = cc$rms_fab;
|
|
FILE *tof;
|
|
int records = 0;
|
|
fab.fab$l_fna = argv[1];
|
|
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
|
tof = fopen(argv[2],"r");
|
|
if (tof == NULL) {
|
|
printf("Could not open file %s\n",argv[1]);
|
|
sts = 0;
|
|
} else {
|
|
if ((sts = sys$open(&fab)) & 1) {
|
|
struct RAB rab = cc$rms_rab;
|
|
rab.rab$l_fab = &fab;
|
|
if ((sts = sys$connect(&rab)) & 1) {
|
|
char rec[MAXREC + 2],cpy[MAXREC + 1];
|
|
rab.rab$l_ubf = rec;
|
|
rab.rab$w_usz = MAXREC;
|
|
while ((sts = sys$get(&rab)) & 1) {
|
|
strcpy(rec + rab.rab$w_rsz,"\n");
|
|
fgets(cpy,MAXREC,tof);
|
|
if (strcmp(rec,cpy) != 0) {
|
|
printf("%%DIFF-F-DIFFERENT Files are different!\n");
|
|
sts = 4;
|
|
break;
|
|
} else {
|
|
records++;
|
|
}
|
|
}
|
|
sys$disconnect(&rab);
|
|
}
|
|
sys$close(&fab);
|
|
}
|
|
fclose(tof);
|
|
if (sts == RMS$_EOF) sts = 1;
|
|
}
|
|
if (sts & 1) {
|
|
printf("%%DIFF-I-Compared %d records\n",records);
|
|
} else {
|
|
printf("%%DIFF-F-Error %d in difference\n",sts);
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
|
|
/* typ: a file TYPE routine */
|
|
|
|
unsigned typ(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
int sts;
|
|
int records = 0;
|
|
struct FAB fab = cc$rms_fab;
|
|
fab.fab$l_fna = argv[1];
|
|
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
|
if ((sts = sys$open(&fab)) & 1) {
|
|
struct RAB rab = cc$rms_rab;
|
|
rab.rab$l_fab = &fab;
|
|
if ((sts = sys$connect(&rab)) & 1) {
|
|
char rec[MAXREC + 2];
|
|
rab.rab$l_ubf = rec;
|
|
rab.rab$w_usz = MAXREC;
|
|
while ((sts = sys$get(&rab)) & 1) {
|
|
unsigned rsz = rab.rab$w_rsz;
|
|
if (fab.fab$b_rat & PRINT_ATTR) rec[rsz++] = '\n';
|
|
rec[rsz++] = '\0';
|
|
fputs(rec,stdout);
|
|
records++;
|
|
}
|
|
sys$disconnect(&rab);
|
|
}
|
|
sys$close(&fab);
|
|
if (sts == RMS$_EOF) sts = 1;
|
|
}
|
|
if ((sts & 1) == 0) {
|
|
printf("%%TYPE-F-ERROR Status: %d\n",sts);
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
|
|
|
|
/* search: a simple file search routine */
|
|
|
|
unsigned search(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
int sts = 0;
|
|
int filecount = 0;
|
|
int findcount = 0;
|
|
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
|
|
struct NAM nam = cc$rms_nam;
|
|
struct FAB fab = cc$rms_fab;
|
|
register char *searstr = argv[2];
|
|
register char firstch = tolower(*searstr++);
|
|
register char *searend = searstr + strlen(searstr);
|
|
{
|
|
char *str = searstr;
|
|
while (str < searend) {
|
|
*str = tolower(*str);
|
|
str++;
|
|
}
|
|
}
|
|
nam = cc$rms_nam;
|
|
fab = cc$rms_fab;
|
|
nam.nam$l_esa = res;
|
|
nam.nam$b_ess = NAM$C_MAXRSS;
|
|
fab.fab$l_nam = &nam;
|
|
fab.fab$l_fna = argv[1];
|
|
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
|
fab.fab$l_dna = "";
|
|
fab.fab$b_dns = strlen(fab.fab$l_dna);
|
|
sts = sys$parse(&fab);
|
|
if (sts & 1) {
|
|
nam.nam$l_rsa = rsa;
|
|
nam.nam$b_rss = NAM$C_MAXRSS;
|
|
fab.fab$l_fop = FAB$M_NAM;
|
|
while ((sts = sys$search(&fab)) & 1) {
|
|
sts = sys$open(&fab);
|
|
if ((sts & 1) == 0) {
|
|
printf("%%SEARCH-F-OPENFAIL, Open error: %d\n",sts);
|
|
} else {
|
|
struct RAB rab = cc$rms_rab;
|
|
rab.rab$l_fab = &fab;
|
|
if ((sts = sys$connect(&rab)) & 1) {
|
|
int printname = 1;
|
|
char rec[MAXREC + 2];
|
|
filecount++;
|
|
rab.rab$l_ubf = rec;
|
|
rab.rab$w_usz = MAXREC;
|
|
while ((sts = sys$get(&rab)) & 1) {
|
|
register char *strng = rec;
|
|
register char *strngend = strng + (rab.rab$w_rsz - (searend - searstr));
|
|
while (strng < strngend) {
|
|
register char ch = *strng++;
|
|
if (ch == firstch || (ch >= 'A' && ch <= 'Z' && ch + 32 == firstch)) {
|
|
register char *str = strng;
|
|
register char *cmp = searstr;
|
|
while (cmp < searend) {
|
|
register char ch2 = *str++;
|
|
ch = *cmp;
|
|
if (ch2 != ch && (ch2 < 'A' || ch2 > 'Z' || ch2 + 32 != ch)) break;
|
|
cmp++;
|
|
}
|
|
if (cmp >= searend) {
|
|
findcount++;
|
|
rec[rab.rab$w_rsz] = '\0';
|
|
if (printname) {
|
|
rsa[nam.nam$b_rsl] = '\0';
|
|
printf("\n******************************\n%s\n\n",rsa);
|
|
printname = 0;
|
|
}
|
|
fputs(rec,stdout);
|
|
if (fab.fab$b_rat & PRINT_ATTR) fputc('\n',stdout);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sys$disconnect(&rab);
|
|
}
|
|
if (sts == SS$_NOTINSTALL) {
|
|
printf("%%SEARCH-W-NOIMPLEM, file operation not implemented\n");
|
|
sts = 1;
|
|
}
|
|
sys$close(&fab);
|
|
}
|
|
}
|
|
if (sts == RMS$_NMF || sts == RMS$_FNF) sts = 1;
|
|
}
|
|
if (sts & 1) {
|
|
if (filecount < 1) {
|
|
printf("%%SEARCH-W-NOFILES, no files found\n");
|
|
} else {
|
|
if (findcount < 1) printf("%%SEARCH-I-NOMATCHES, no strings matched\n");
|
|
}
|
|
} else {
|
|
printf("%%SEARCH-F-ERROR Status: %d\n",sts);
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
|
|
/* del: you don't want to know! */
|
|
|
|
unsigned del(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
int sts = 0;
|
|
struct NAM nam = cc$rms_nam;
|
|
struct FAB fab = cc$rms_fab;
|
|
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
|
|
int filecount = 0;
|
|
nam.nam$l_esa = res;
|
|
nam.nam$b_ess = NAM$C_MAXRSS;
|
|
fab.fab$l_nam = &nam;
|
|
fab.fab$l_fna = argv[1];
|
|
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
|
printf("WARNING! This bit is broken - volume corruption VERY likely!\n");
|
|
sts = sys$parse(&fab);
|
|
if (sts & 1) {
|
|
if (nam.nam$b_ver < 2) {
|
|
printf("%%DELETE-F-NOVER, you must specify a version!!\n");
|
|
} else {
|
|
nam.nam$l_rsa = rsa;
|
|
nam.nam$b_rss = NAM$C_MAXRSS;
|
|
fab.fab$l_fop = FAB$M_NAM;
|
|
while ((sts = sys$search(&fab)) & 1) {
|
|
sts = sys$erase(&fab);
|
|
if ((sts & 1) == 0) {
|
|
printf("%%DELETE-F-DELERR, Delete error: %d\n",sts);
|
|
} else {
|
|
filecount++;
|
|
rsa[nam.nam$b_rsl] = '\0';
|
|
printf("%%DELETE-I-DELETED, Deleted %s\n",rsa);
|
|
}
|
|
}
|
|
if (sts == RMS$_NMF) sts = 1;
|
|
}
|
|
if (sts & 1) {
|
|
if (filecount < 1) {
|
|
printf("%%DELETE-W-NOFILES, no files deleted\n");
|
|
}
|
|
} else {
|
|
printf("%%DELETE-F-ERROR Status: %d\n",sts);
|
|
}
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
|
|
/* show: the show command */
|
|
|
|
unsigned show(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
unsigned sts = 1;
|
|
if (keycomp(argv[1],"default")) {
|
|
unsigned short curlen;
|
|
char curdir[NAM$C_MAXRSS + 1];
|
|
struct dsc$descriptor curdsc;
|
|
curdsc.dsc$w_length = NAM$C_MAXRSS;
|
|
curdsc.dsc$a_pointer = curdir;
|
|
if ((sts = sys$setddir(NULL,&curlen,&curdsc)) & 1) {
|
|
curdir[curlen] = '\0';
|
|
printf(" %s\n",curdir);
|
|
} else {
|
|
printf("Error %d getting default\n",sts);
|
|
}
|
|
} else {
|
|
if (keycomp(argv[1],"time")) {
|
|
char timstr[24];
|
|
unsigned short timlen;
|
|
struct dsc$descriptor timdsc;
|
|
timdsc.dsc$w_length = 23;
|
|
timdsc.dsc$a_pointer = timstr;
|
|
sys$asctim(&timlen,&timdsc,NULL,0);
|
|
timstr[timlen] = '\0';
|
|
printf(" %s\n",timstr);
|
|
} else {
|
|
printf("%%SHOW-W-WHAT '%s'?\n",argv[1]);
|
|
}
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
/* set: the set command */
|
|
|
|
unsigned set(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
unsigned sts = 1;
|
|
if (keycomp(argv[1],"default")) {
|
|
struct dsc$descriptor defdsc;
|
|
defdsc.dsc$a_pointer = argv[2];
|
|
defdsc.dsc$w_length = strlen(defdsc.dsc$a_pointer);
|
|
if (((sts = sys$setddir(&defdsc,NULL,NULL)) & 1) == 0) {
|
|
printf("Error %d setting default to %s\n",sts,argv[2]);
|
|
}
|
|
} else {
|
|
printf("%%SET-W-WHAT '%s'?\n",argv[1]);
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
|
|
#ifndef VMSIO
|
|
|
|
/* The bits we need when we don't have real VMS routines underneath... */
|
|
|
|
unsigned dodismount(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
struct DEV *dev;
|
|
register int sts = device_lookup(strlen(argv[1]),argv[1],0,&dev);
|
|
if (sts & 1) {
|
|
if (dev->vcb != NULL) {
|
|
sts = dismount(dev->vcb);
|
|
} else {
|
|
sts = SS$_DEVNOTMOUNT;
|
|
}
|
|
}
|
|
if ((sts & 1) == 0) printf("%%DISMOUNT-E-STATUS Error: %d\n",sts);
|
|
return sts;
|
|
}
|
|
|
|
char *mouquals[] = {"write",NULL};
|
|
|
|
unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
char *dev = argv[1];
|
|
char *lab = argv[2];
|
|
int sts = 1,devices = 0;
|
|
char *devs[100],*labs[100];
|
|
int options = checkquals(mouquals,qualc,qualv);
|
|
while (*lab != '\0') {
|
|
labs[devices++] = lab;
|
|
while (*lab != ',' && *lab != '\0') lab++;
|
|
if (*lab != '\0') {
|
|
*lab++ = '\0';
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
devices = 0;
|
|
while (*dev != '\0') {
|
|
devs[devices++] = dev;
|
|
while (*dev != ',' && *dev != '\0') dev++;
|
|
if (*dev != '\0') {
|
|
*dev++ = '\0';
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (devices > 0) {
|
|
unsigned i;
|
|
struct VCB *vcb;
|
|
sts = mount(options,devices,devs,labs,&vcb);
|
|
if (sts & 1) {
|
|
for (i = 0; i < vcb->devices; i++)
|
|
if (vcb->vcbdev[i].dev != NULL)
|
|
printf("%%MOUNT-I-MOUNTED, Volume %12.12s mounted on %s\n",
|
|
vcb->vcbdev[i].home.hm2$t_volname,vcb->vcbdev[i].dev->devnam);
|
|
} else {
|
|
printf("Mount failed with %d\n",sts);
|
|
}
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
|
|
void directshow(void);
|
|
void phyio_show(void);
|
|
|
|
/* statis: print some simple statistics */
|
|
|
|
unsigned statis(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
printf("Statistics:-\n");
|
|
directshow();
|
|
cacheshow();
|
|
phyio_show();
|
|
return 1;
|
|
}
|
|
|
|
/* dump: a simple debugging aid */
|
|
|
|
unsigned dump(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
printf("Cache Dump:-\n");
|
|
cachedump();
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
|
|
/* help: a routine to print a pre-prepared help text... */
|
|
|
|
unsigned help(int argc,char *argv[],int qualc,char *qualv[])
|
|
{
|
|
printf("\nODS2 v1.2\n");
|
|
printf(" Please send problems/comments to Paulnank@au1.ibm.com\n");
|
|
printf(" Commands are:\n");
|
|
printf(" copy difference directory exit\n");
|
|
printf(" mount show_default show_time search\n");
|
|
printf(" set_default type\n");
|
|
printf(" Example:-\n $ mount e:\n");
|
|
printf(" $ search e:[vms$common.decc*...]*.h rms$_wld\n");
|
|
printf(" $ set default e:[sys0.sysmgr]\n");
|
|
printf(" $ copy *.com;-1 c:\\*.*\n");
|
|
printf(" $ directory/file/size/date [-.sys*...].%%\n");
|
|
printf(" $ exit\n");
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* informaion about the commands we know... */
|
|
|
|
struct CMDSET {
|
|
char *name;
|
|
unsigned (*proc) (int argc,char *argv[],int qualc,char *qualv[]);
|
|
unsigned int minlen;
|
|
unsigned int minargs;
|
|
unsigned int maxargs;
|
|
unsigned int maxquals;
|
|
} cmdset[] = {
|
|
{
|
|
"copy",copy,3,3,3,0
|
|
},
|
|
{
|
|
"delete",del,3,2,2,0
|
|
},
|
|
{
|
|
"difference",diff,3,3,3,0
|
|
},
|
|
{
|
|
"directory",dir,3,1,2,6
|
|
},
|
|
{
|
|
"exit",NULL,2,0,0,0
|
|
},
|
|
{
|
|
"help",help,2,1,1,0
|
|
},
|
|
{
|
|
"show",show,2,2,2,0
|
|
},
|
|
{
|
|
"search",search,3,3,3,0
|
|
},
|
|
{
|
|
"set",set,3,2,3,0
|
|
},
|
|
#ifndef VMSIO
|
|
{
|
|
"dismount",dodismount,3,2,2,0
|
|
},
|
|
{
|
|
"mount",domount,3,2,3,2
|
|
},
|
|
{
|
|
"statistics",statis,3,1,1,0
|
|
},
|
|
{
|
|
"dump",dump,3,1,1,0
|
|
},
|
|
#endif
|
|
{
|
|
"type",typ,3,2,2,0
|
|
},
|
|
{
|
|
NULL,NULL,0,0,0,0
|
|
}
|
|
};
|
|
|
|
|
|
/* cmdexecute: identify and execute a command */
|
|
|
|
int cmdexecute(unsigned int argc,char *argv[],unsigned int qualc,char *qualv[])
|
|
{
|
|
char *ptr = argv[0];
|
|
struct CMDSET *cmd = cmdset;
|
|
unsigned cmdsiz = strlen(ptr);
|
|
while (*ptr != '\0') {
|
|
*ptr = tolower(*ptr);
|
|
ptr++;
|
|
}
|
|
while (cmd->name != NULL) {
|
|
if (cmdsiz >= cmd->minlen && cmdsiz <= strlen(cmd->name)) {
|
|
if (keycomp(argv[0],cmd->name)) {
|
|
if (cmd->proc == NULL) {
|
|
return 0;
|
|
} else {
|
|
if (argc < cmd->minargs || argc > cmd->maxargs) {
|
|
printf("%%ODS2-E-PARAMS, Incorrect number of command parameters\n");
|
|
} else {
|
|
if (qualc > cmd->maxquals) {
|
|
printf("%%ODS2-E-QUALS, Too many command qualifiers\n");
|
|
} else {
|
|
(*cmd->proc) (argc,argv,qualc,qualv);
|
|
#ifndef VMSIO
|
|
cacheflush();
|
|
#endif
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
cmd++;
|
|
}
|
|
printf("%%ODS2-E-ILLCMD, Illegal or ambiguous command '%s'\n",argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
/* cmdsplit: break a command line into its components */
|
|
|
|
int cmdsplit(char *str)
|
|
{
|
|
int argc = 0,qualc = 0;
|
|
char *argv[32],*qualv[32];
|
|
char *sp = str;
|
|
int i;
|
|
for (i = 0; i < 32; i++) argv[i] = qualv[i] = "";
|
|
while (*sp != '\0') {
|
|
while (*sp == ' ') sp++;
|
|
if (*sp != '\0') {
|
|
if (*sp == '/') {
|
|
*sp++ = '\0';
|
|
qualv[qualc++] = sp;
|
|
} else {
|
|
argv[argc++] = sp;
|
|
}
|
|
while (*sp != ' ' && *sp != '/' && *sp != '\0') sp++;
|
|
if (*sp == '\0') {
|
|
break;
|
|
} else {
|
|
if (*sp != '/') *sp++ = '\0';
|
|
}
|
|
}
|
|
}
|
|
if (argc > 0) return cmdexecute(argc,argv,qualc,qualv);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* main: the simple mainline of this puppy... */
|
|
|
|
int main(int argc,char *argv[])
|
|
{
|
|
char str[2048];
|
|
str[sizeof(str)-1] = 0;
|
|
printf(" ODS2 v1.2\n");
|
|
while (1) {
|
|
printf("$> ");
|
|
if (fgets(str, sizeof(str)-1, stdin) == NULL) break;
|
|
if (strlen(str)) if ((cmdsplit(str) & 1) == 0) break;
|
|
}
|
|
return 1;
|
|
}
|