#include #include #include #include #include #include #include "nufind.h" #include "queue.h" struct DateSel { unsigned Date; int Swt; }; char *RootPath(char *CurDir, char *RelPath, char *FullPath); void GetStdIn(QUE_DEF * Que, char *Prompt); int GetList(QUE_DEF * Que, char *argv[], int i, char *Prompt, char *PathName); void ErrorExit(char *Format,...); void ErrorMsg(char *Format,...); void ExceptionMsg(char *Format,...); int GetAttr(char **Str, int i); int MakeDir(char *Name); int GetDate(char **argv, int i, struct DateSel * Date); long GtoJ(unsigned m, unsigned d, unsigned y); void JtoG(long Julian, int *Month, int *Day, int *Year); int isdevice(int handle); int GetDirRef(char **Ref, char **argv, int i); int GetFileRef(INFO_BLOCK ** Ref, char **argv, int i); void GetPath(QUE_DEF * Q, char *Arg); int GetYorN(char *Message,...); int CheckPath (QUE_DEF *Q, char *Name); void SetCopyMove (char *argv[], int *i, int *Swt); static char *OptTable[] = { #define O_NAME 0 "name", #define O_NAME_SHORT 1 "n", #define O_NOT_NAME 2 "^name", #define O_NOT_NAME_SHORT 3 "^n", #define O_FNAME 4 "fname", #define O_FNAME_SHORT 5 "fn", #define O_NOT_FNAME 6 "^fname", #define O_NOT_FNAME_SHORT 7 "^fn", #define O_SILENT 8 "s", #define O_PRINT 9 "p", #define O_LS 10 "ls", #define O_LD 11 "ld", #define O_REMOVE 12 "rm", #define O_REMOVE_ALL 13 "rma", #define O_ATTR 14 "attr", #define O_NOT_ATTR 15 "^attr", #define O_ATTR_ON 16 "attr+", #define O_ATTR_OFF 17 "attr-", #define O_NO_RECUR 18 "nr", #define O_COPY 19 "cp", #define O_MOVE 20 "mv", #define O_SINCE 21 "si", #define O_BEFORE 22 "be", #define O_SIZE 23 "size", #define O_REMOVE_DIR 24 "rmdir", #define O_EXEC 25 "exec", #define O_EXEC_SHORT 26 "ex", #define O_TREE 27 "t", #define O_SUM 28 "sum", #define O_EXIST 29 "exist", #define O_NOT_EXIST 30 "^exist", #define O_COMP 31 "comp", #define O_NOT_COMP 32 "^comp", #define O_LT 33 "lt", #define O_LE 34 "le", #define O_GT 35 "gt", #define O_GE 36 "ge", #define O_LT_DATE 37 "ltdate", #define O_LE_DATE 38 "ledate", #define O_GT_DATE 39 "gtdate", #define O_GE_DATE 40 "gedate", #define O_RELATIVE 41 "re", #define O_NOT_PATH 42 "^dir", #define O_NOT_PATH_SHORT 43 "^d", #define O_MOVE_TREE 44 "mt", #define O_COPY_TREE 45 "ct", #define O_COPY_TREE_DATE 46 "cto", #define O_COPY_DATE 47 "cpo", #define O_KILL 48 "kill", #define O_INVALID 49 "" }; void GetArgs (char *argv[], int i) { extern QUE_DEF Paths, ExcPaths; extern QUE_DEF IncNameQueue, ExcNameQueue; extern QUE_DEF IncPathQueue, ExcPathQueue; extern char DestDir[], CurDir[]; extern int PrtSwt, LsSwt, LdSwt, RmSwt, RmSwtA, AttrSwt, NotAttrSwt; extern int AttrOnSwt, AttrOffSwt, RecurSwt, CopySwt, MoveSwt, RmDirSwt; extern int SizeSwt, ExecSwt, TreeSwt, SumSwt, RelSwt, OldDate; extern char AttrMask, NotAttrMask, AttrOnMask, AttrOffMask; extern char *ExistRef, *NotExistRef, *CompRef, *NotCompRef; extern INFO_BLOCK *LT_Ref, *LE_Ref, *GT_Ref, *GE_Ref; extern INFO_BLOCK *LT_DateRef, *LE_DateRef, *GT_DateRef, *GE_DateRef; extern char *CommandString; extern unsigned TodayDate; extern long Size; extern struct DateSel Since, Before; char *Arg, PathName[65]; int j; for (; argv[i] != NULL; ++i) { if (**(argv + i) != '-') continue; Arg = (*(argv + i)) + 1; for (j = 0; OptTable[j][0] != '\0'; ++j) if (!strcmp(Arg, OptTable[j])) break; switch (j) { case O_NOT_PATH: case O_NOT_PATH_SHORT: for (++i; argv[i] != NULL && argv[i][0] != '-'; ++i) GetPath(&ExcPaths, argv[i]); if (argv[i][0] == '-') --i; break; case O_NAME: case O_NAME_SHORT: i = GetList(&IncNameQueue, argv, i, "-name:", NULL); continue; case O_NOT_NAME: case O_NOT_NAME_SHORT: i = GetList(&ExcNameQueue, argv, i, "-^name:", NULL); continue; case O_FNAME: case O_FNAME_SHORT: i = GetList(&IncPathQueue, argv, i, "-fname:", PathName); continue; case O_NOT_FNAME: case O_NOT_FNAME_SHORT: i = GetList(&ExcPathQueue, argv, i, "-^fname:", PathName); continue; case O_SILENT: PrtSwt = 0; break; case O_PRINT: PrtSwt |= 0x02; break; case O_LS: LsSwt = 1; PrtSwt &= 0xFE; break; case O_LD: LdSwt = 1; PrtSwt &= 0xFE; break; case O_REMOVE: RmSwt = 1; PrtSwt &= 0xFE; break; case O_REMOVE_ALL: RmSwtA = 1; PrtSwt &= 0xFE; break; case O_REMOVE_DIR: RmDirSwt = 1; PrtSwt &= 0xFE; break; case O_ATTR: AttrMask = GetAttr(argv, ++i); AttrSwt = 1; break; case O_NOT_ATTR: NotAttrMask = GetAttr(argv, ++i); NotAttrSwt = 1; break; case O_ATTR_ON: AttrOnMask = GetAttr(argv, ++i); PrtSwt &= 0xFE; AttrOnSwt = 1; break; case O_ATTR_OFF: AttrOffMask = GetAttr(argv, ++i); PrtSwt &= 0xFE; AttrOffSwt = 1; break; case O_NO_RECUR: RecurSwt = 0; break; case O_COPY_TREE_DATE: OldDate = 1; case O_COPY_TREE: TreeSwt = 1; SetCopyMove(argv, &i, &CopySwt); break; case O_COPY_DATE: OldDate = 1; case O_COPY: SetCopyMove(argv, &i, &CopySwt); break; case O_MOVE_TREE: TreeSwt = 1; RmDirSwt = 1; SetCopyMove(argv, &i, &MoveSwt); break; case O_MOVE: SetCopyMove(argv, &i, &MoveSwt); break; case O_SINCE: i = GetDate(argv, i, &Since); break; case O_BEFORE: i = GetDate(argv, i, &Before); break; case O_SIZE: if ( argv[i + 1][0] == '\0' || (argv[i + 1][0] == '-' && !isdigit(argv[i + 1][1])) ) ErrorExit("\"%s\" Size argument required.\n", argv[i]); else if (isdigit(argv[i + 1][0])) { Size = atol(argv[++i]); SizeSwt = 1; } else if (argv[i + 1][0] == '-' && isdigit(argv[i + 1][1])) { Size = atol(argv[++i] + 1); SizeSwt = 2; } else ErrorExit("\"%s\" Invalid size - %s\n", argv[i], argv[i + 1]); break; case O_EXEC: case O_EXEC_SHORT: if (argv[i + 1][0] == '\0' || argv[i + 1][0] == '-') ErrorExit("\"%s\" Command required.\n", argv[i]); ExecSwt = 1; PrtSwt &= 0xFE; CommandString = strdup(argv[++i]); break; case O_TREE: TreeSwt = 1; break; case O_SUM: SumSwt = 1; break; case O_EXIST: i = GetDirRef(&ExistRef, argv, i); break; case O_NOT_EXIST: i = GetDirRef(&NotExistRef, argv, i); break; case O_COMP: i = GetDirRef(&CompRef, argv, i); break; case O_NOT_COMP: i = GetDirRef(&NotCompRef, argv, i); break; case O_LT: i = GetFileRef(<_Ref, argv, i); break; case O_LE: i = GetFileRef(&LE_Ref, argv, i); break; case O_GT: i = GetFileRef(>_Ref, argv, i); break; case O_GE: i = GetFileRef(&GE_Ref, argv, i); break; case O_LT_DATE: i = GetFileRef(<_DateRef, argv, i); break; case O_LE_DATE: i = GetFileRef(<_DateRef, argv, i); break; case O_GT_DATE: i = GetFileRef(>_DateRef, argv, i); break; case O_GE_DATE: i = GetFileRef(&GE_DateRef, argv, i); break; case O_RELATIVE: RelSwt = 1; break; case O_KILL: RmSwt = 1; RmDirSwt = 1; PrtSwt &= 0xFE; break; default: ErrorExit("Invalid option: %s", Arg); } } } int GetList (QUE_DEF * Que, char *argv[], int i, char *Prompt, char *PathName) { extern char CurDir[]; FILE *F1; char Line[80]; if (!strcmp(argv[i + 1], "-")) { GetStdIn(Que, Prompt); ++i; } else if (argv[i + 1][0] == '@') { if ((F1 = fopen(&argv[i + 1][1], "r")) == NULL) ErrorExit("I can't find index file: %s!\n", &argv[i + 1][1]); while (fgets(Line, 79, F1) != NULL) { if (Line[strlen(Line) - 1] == '\n') Line[strlen(Line) - 1] = '\0'; else ErrorExit("Index file: %s - Line too long\n %s\n", &argv[i + 1][1], Line); if (PathName != NULL) { if ((Enque(Que, strlwr(RootPath(CurDir, Line, PathName)))) == NULL) { ErrorMsg("Insufficient memory for input list.\n"); return (i); } } else if ((Enque(Que, strlwr(Line))) == NULL) { ErrorMsg("Insufficient memory for input list.\n"); return (i); } } fclose(F1); i += 1; } else { for (++i; argv[i] != NULL && argv[i][0] != '-'; ++i) if (PathName != NULL) { if ((Enque(Que, strlwr(RootPath(CurDir, argv[i], PathName)))) == NULL) { ErrorMsg("Insufficient memory for input list.\n"); return (i); } } else if ((Enque(Que, strlwr(argv[i]))) == NULL) { ErrorMsg("Insufficient memory ofr input list.\n"); return (i); } --i; } return (i); } void GetStdIn (QUE_DEF *Que, char *Prompt) { char Line[80]; while (1) { if (isdevice(fileno(stdin))) fprintf(stderr, "%s ", Prompt); if (gets(Line) == NULL) break; if (Line[0] == '\0') break; if ((Enque(Que, Line)) == NULL) { ErrorMsg("Insufficient memory for input lst.\n"); return; } } } int GetAttr (char **Str, int i) { char Ch; int j, Mask; if (Str[i][0] == '\0' || Str[i][0] == '-') ErrorExit("\"%s\" must be followed by a list of attributes.", Str[i - 1]); Mask = j = 0; while ((Ch = tolower(Str[i][j++])) != '\0') switch (Ch) { case 'r': Mask |= 0x01; break; case 'h': Mask |= 0x02; break; case 's': Mask |= 0x04; break; case 'v': Mask |= 0x08; break; case 'd': Mask |= 0x10; break; case 'a': Mask |= 0x20; break; default: ErrorExit("\"%s\" Invalid attribute: %s", Str[i - 1], Str[i]); } return (Mask); } int MakeDir (char *Name) { extern QUE_DEF NoCreateQ; struct ffblk DirBlk; char *p, Temp[66]; int Result; if (NoCreateQ.Count != 0) if ( CheckPath(&NoCreateQ, Name) != 0 ) return(0); p = strrchr(Name, '\\'); if (*(p - 1) == ':') return (0); *p = '\0'; Result = findfirst(Name, &DirBlk, 0xFF); if (Result || (DirBlk.ff_attrib & FA_DIREC) == 0) { if ((Result = MakeDir(Name)) != 0) return (Result); if ( !GetYorN("Directory %s does not exist. Create it ", Name) ) { strcpy(Temp, Name); strcat(Temp, "\\*"); Enque(&NoCreateQ, Temp); return(2); } if ((Result = mkdir(Name)) == 0) { strcpy(Temp, Name); strcat(Temp, "\\*"); Enque(&ExcPathQueue, Temp); } else { strcpy(Temp, Name); strcat(Temp, "\\*"); Enque(&NoCreateQ, Temp); } } *p = '\\'; return (Result); } int GetDate (char **argv, int i, struct DateSel * Date) { unsigned long Today; int Arg1, Arg2, Arg3; int Year, Month, Day; char *p, Temp[3], *Str; if ( (argv[i + 1] == NULL) || (argv[i + 1][0] == '\0') || (argv[i + 1][0] == '-' && !isdigit(argv[i + 1][1]))) { Date->Date = TodayDate; Date->Swt = 1; return (i); } if (argv[i + 1] != NULL && isdigit(argv[i + 1][0])) { Str = argv[++i]; p = &Str[strcspn(Str, "-/")]; if (*p != 0) { *p = '\0'; Arg1 = atoi(Str); Str = ++p; p = &Str[strcspn(Str, "-/")]; if (*p == '\0') ErrorExit("\"%s\" Invalid date - %s\n", argv[i - 1], argv[i]); *p = '\0'; Arg2 = atoi(Str); Arg3 = atoi(p + 1); } else if (strlen(Str) > 2) { strncpy(Temp, Str, 2); Temp[2] = '\0'; Arg1 = atoi(Temp); strncpy(Temp, Str + 2, 2); Temp[2] = '\0'; Arg2 = atoi(Temp); strncpy(Temp, Str + 4, 2); Temp[2] = '\0'; Arg3 = atoi(Temp); } else { Today = GtoJ((TodayDate >> 5) & 0x0F, TodayDate & 0x1F, (TodayDate >> 9) & 0x7F); i = atoi(Str); JtoG(Today - i, &Arg1, &Arg2, &Arg3); Arg3 += 80; } if (Arg1 > 31) { Year = Arg1; Month = Arg2; Day = Arg3; } else { Year = Arg3; Month = Arg1; Day = Arg2; } if (Month > 12 || Day > 31) ErrorExit("\"%s\" Invalid date - %s\n", argv[i - 1], argv[i]); if (Year > 100) Year -= 1980; else Year -= 80; } Date->Date = (Year << 9) | (Month << 5) | Day; Date->Swt = 1; return (i); } /************************************************************************/ /* *** GtoJ.c *** */ /* */ /* This function converts a gregorian date, in the ( month, day, year ) */ /* format, into its respective julian, or day number, equivalent. */ /* ( 1 = 1st day AD ) */ /* */ /* The legal input values, in their proper order, are: */ /* */ /* month = 1 to 12 ( unsigned int ) */ /* day = 1 to 31 ( unsigned int ) */ /* year = 0 to 9999 ( unsigned int ) */ /* */ /* The return value of the function is the julian day number */ /* expressed as an unsigned long integer. */ /* */ /************************************************************************/ long GtoJ (unsigned m, unsigned d, unsigned y) { y += (m += 9) / 12 + 399; m %= 12; return ((long) y * 365 + y / 4 - y / 100 + y / 400 + (153 * m + 2) / 5 + d - 146037L); } /************************************************************************/ /* *** JtoG.c *** */ /* */ /* This function converts a julian day number ( 1 = 1st day AD ), into */ /* either a gregorian date character string, in any one of the four */ /* formats described below, or an array of three integers representing */ /* the month, day, and year, respectively, of the equivalent gregorian */ /* date. Storage for the output is provided by the calling routine. */ /* */ /* The input values, in their proper order, are: */ /* */ /* 1. the julian date to be converted, ( unsigned long ) */ /* */ /* 2. a pointer to the output array, ( char * ) */ /* */ /* 3. the format code ( described below ) */ /* specifying the desired output format. ( unsigned int ) */ /* */ /* The format codes are defined as follows: */ /* */ /* CODE - EXPLANATION - */ /* */ /* 0 - output array will hold three integers defined as: */ /* */ /* array[0] = month ( mm ) */ /* array[1] = day ( dd ) */ /* array[2] = Year ( yyyy ) */ /* */ /* If this format option is used, a type cast will have to */ /* be performed on the output pointer to convert it to the */ /* appropriate pointer type. ( see example below ) */ /* */ /* 1 - output string will hold a character string in the */ /* format "mmddyy" ( minimum - char string[7] ) */ /* */ /* 2 - output string will hold a character string in the */ /* format "mmddyyyy" ( minimum - char string[9] ) */ /* */ /* 3 - output string will hold a character string in the */ /* format "mm/dd/yy" ( minimum - char string[9] ) */ /* */ /* 4 - output string will hold a character string in the */ /* format "mm/dd/yyyy" ( minimum - char string[11] ) */ /* */ /* NOTE - input of any format code not listed above will be */ /* interpreted as code 0. */ /* */ /* The function returns a character pointer to the output array. */ /* _________________________________________________________________ */ /* | *** example of integer array output *** | */ /* | | */ /* | int Month, dte_array[3]; | */ /* | long julian = 548784; | */ /* | | */ /* | Month = ( (int *)JtoG( Julian, (char *)dte_array, 0 ) )[0]; | */ /* |________________________________________________________________| */ /* */ /* WARNING - the output array pointed to must be dimensioned */ /* accordingly or a memory overwrite will occur. */ /************************************************************************/ void JtoG (long Julian, int *Month, int *Day, int *Year) { *Year = (int) ((Julian += 146037L) * 400 / 146097L); Julian -= (long) *Year * 365 + *Year / 4 - *Year / 100 + *Year / 400; if (!Julian) Julian = 365 + !(*Year % 4), --*Year; *Year += (*Month = (*Day = (int) Julian * 5 - 3) / 153 + 2) / 12 - 400; *Month = *Month % 12 + 1; *Day = *Day % 153 / 5 + 1; } /* * ISDEVICE - Will invoke Ms-Dos IOCTL function to "get" the attributes of * the specified DOS handle. * * Result := True If the specified handle is a device. * := False If the specified handle is a file. * * Caution: A True return only indicates that the handle is assigned to a device * driver. These include the CON, PRN, AUX and any user installed device * drivers. * * A False return indicates that the handle is assigned to a file that may be on * a Floppy, Hard Disk or Ram Disk. */ int isdevice (int handle) { union REGS R; R.x.ax = 0x4400; /* MS-DOS IOCTL "Get" function */ R.x.bx = handle; /* ... Handle for IOCTL "Get" */ R.x.dx = 0; intdos(&R, &R); /* ... MS-DOS Entry Interrupt */ if ((R.x.dx & 0x80) == 0) return (0); else return (1); } int GetDirRef (char **Ref, char **argv, int i) { if (argv[i + 1][0] == '\0' || argv[i + 1][0] == '-') ErrorExit("\"%s\" requires a directory argument.", argv[i]); if ((*Ref = malloc(66)) == NULL) ErrorMsg("Insufficient memory for \"%s\".", argv[i]); else RootPath(CurDir, argv[++i], *Ref); return (i); } int GetFileRef (INFO_BLOCK **Ref, char **argv, int i) { struct ffblk DirBlk; if (argv[i + 1][0] == '\0' || argv[i + 1][0] == '-') ErrorExit("\"%s\" requires a filename argument.", argv[i]); if ((*Ref = malloc(sizeof(INFO_BLOCK))) == NULL) ErrorMsg("Insufficient memory for \"%s\" reference.", argv[i]); else { RootPath(CurDir, argv[++i], (*Ref)->Name); if (findfirst((*Ref)->Name, &DirBlk, (FA_SYSTEM | FA_RDONLY | FA_HIDDEN | FA_ARCH))) ErrorExit("\"%s\" - %s", argv[i - 1], argv[i]); (*Ref)->Attrib = DirBlk.ff_attrib; (*Ref)->FTime.Time = DirBlk.ff_ftime; (*Ref)->FDate.Date = DirBlk.ff_fdate; (*Ref)->Size = DirBlk.ff_fsize; } return (i); } void SetCopyMove (char *argv[], int *i, int *Swt) { char *p; if (argv[*i + 1] == NULL || argv[*i + 1][0] == '-') strcpy(DestDir, CurDir); else if ( !strcmp(argv[*i + 1], ".") ) strcpy(DestDir, CurDir); else if ( !strcmp(argv[*i + 1], "..") ) { CurDir[strlen(CurDir)-1] = '\0'; *(p = strrchr(CurDir, '\\')) = '\0'; strcpy(DestDir, CurDir); strcat(DestDir, "\\"); *p = '\\'; strcat(CurDir, "\\"); } else RootPath(CurDir, argv[++*i], DestDir); *Swt = 1; PrtSwt &= 0xFE; }