home *** CD-ROM | disk | FTP | other *** search
- /*
- * treewalk - a command to get the power of treewalk out to the CLI.
- *
- * Copyright (C) 1989 Mike Meyer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 1, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <exec/types.h>
- #include <libraries/dos.h>
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/intuition.h>
- #include <dos.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "treewalk.h"
- #include "errors.h"
-
- /*
- * Filter parsing functions, prototypes thereof. The "void *"'s are a lie,
- * but they serve their purpose.
- */
- void *parse(char *) ;
- long execute(struct FileInfoBlock *, void *) ;
-
- /* Flags needed by the visit function, to help it decide what to do */
- static int singlearg = FALSE, verbose = FALSE, ignore = FALSE ;
- static void *code = NULL ;
-
- /* Things visible to other files */
- char *my_name ;
- int errorflag = ERROR_NONE ;
-
- /*
- * And the functions I need from below.
- */
- static int dofiles(long, struct FileInfoBlock *) ;
-
- /*
- * We need storage for the duration of a filter execution. We use
- * the RememberKey and free it after the execution.
- */
- static struct Remember *filterstrings = NULL ;
-
- /*
- * Things for dealing with a issuance of commands
- */
- #define COMMAX 240 /* WShell is 240, stock would be 256 */
- static char command[COMMAX] = "", *commnext = command, *commend ;
-
- static void
- growcommand(char *stuff, int pad) {
-
- strcpy(commnext, stuff) ;
- commnext += strlen(stuff) ;
- if (!pad) return ;
- *commnext++ = ' ' ;
- *commnext = '\0' ;
- }
-
- static void
- endcommand(void) {
-
- commend = commnext ;
- }
-
- static void
- docommand(void) {
-
- if (verbose) fprintf(stderr, "Executing: %s\n", command) ;
- Execute(command, NULL, NULL) ;
- if (!ignore && IoErr()) {
- errorflag = ERROR_WARN ;
- if (verbose) fprintf(stderr, "Error from command\n") ;
- else fprintf(stderr, "Error from command '%s'\n", command) ;
- }
- *commend = '\0' ;
- commnext = commend ;
- }
-
- void
- main(int argc, char **argv) {
- int treeflags = TREE_PRE, stat ;
- char *rootdir = "", *filter = NULL ;
- long root ;
-
- my_name = argv[0] ;
-
- if ((IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 33)) == NULL) {
- fprintf(stderr, "%s: Can't open intuition.library\n", my_name) ;
- exit(20) ;
- }
-
- /* Argument parsing time again... */
- while (*++argv)
- if (!strcmp(*argv, "?")) {
- fprintf(stderr, "usage: %s [options] [command]\n", my_name) ;
- fprintf(stderr, "options: [post|both] [single] [verbose] [ignore] [dir <dir>] [filter <filter>] [command]\n") ;
- exit(RETURN_OK) ;
- }
- else if (!strnicmp(*argv, "single", 3)) singlearg = TRUE ;
- else if (!strnicmp(*argv, "verbose", 3)) verbose = TRUE ;
- else if (!strnicmp(*argv, "ignore", 3)) ignore = TRUE ;
- else if (!strnicmp(*argv, "post", 3)) treeflags = TREE_POST ;
- else if (!strnicmp(*argv, "both", 3)) treeflags = TREE_BOTH ;
- else if (!strnicmp(*argv, "dir", 3)) rootdir = *++argv ;
- else if (!strnicmp(*argv, "filter", 3)) filter = *++argv ;
- else if (!strnicmp(*argv, "command", 3)) {
- argv += 1 ;
- break ;
- }
- else break ; /* Start of command */
-
- /* Check for filter */
- if (filter) {
- if ((code = parse(filter)) == NULL) {
- fprintf(stderr, "%s: exiting\n", my_name) ;
- exit(RETURN_ERROR) ;
- }
- if (filterstrings) {
- FreeRemember(&filterstrings, FALSE) ;
- filterstrings = NULL ;
- }
- }
-
- /*
- * Now, stack up commands. Command is large enough to hold any valid
- * command, so it must be large enough to hold the tail of this one.
- */
- while (*argv)
- growcommand(*argv++, TRUE) ;
- endcommand() ;
-
- if ((root = Lock(rootdir, ACCESS_READ)) == NULL) {
- fprintf(stderr, "%s: Can't lock %s\n", my_name, rootdir) ;
- exit(RETURN_ERROR) ;
- }
-
- treewalk(root, dofiles, treeflags) ;
- UnLock(root) ;
-
- /* Clean up any leftover commands */
- if (*commend) docommand() ;
-
- /* Tell the user how we exited, if need be */
- switch (errorflag) {
- case ERROR_BREAK: printf("*** Break: %s\n", my_name) ;
- /* Fall through to next case */
-
- case ERROR_NONE: stat = 0;
- break ;
-
- case ERROR_WARN: stat = RETURN_WARN ;
- break ;
-
- case ERROR_HALT: stat = RETURN_ERROR ;
- fprintf(stderr, "%s: Execution halting\n", my_name) ;
- break ;
- }
- exit(stat) ;
- }
-
- /*
- * And now, where all the work is really done. Various things for dealing
- * filtering out files, getting their true name, and building & executing
- * commands.
- */
-
- /*
- * pathname code: is either a valid pathname, or a "". Getpathname makes it
- * hold the right thing, or return TRUE ;
- */
- static char pathname[FMSIZE] = "" ;
-
- static int
- getpathname(long lock) {
-
- if (getpath(lock, pathname)) {
- fprintf(stderr, "%s: Failure in getting full path name!\n",
- my_name) ;
- *pathname = '\0' ;
- errorflag = ERROR_HALT ;
- return TRUE ;
- }
- strcat(pathname, strchr(pathname, ':') == NULL ? ":" : "/") ;
- return FALSE ;
- }
-
- /*
- * Some globals for use by the primitives below. The values don't change
- * during one filter execution, so it don't matter much.
- */
- static long lock_global ;
-
- /*
- * The visit function - where all the work is actually done...
- */
- static int
- dofiles(long lock, struct FileInfoBlock *fib) {
- int status ;
-
- /* First, check to see if we need to stop */
- if (errorflag == ERROR_HALT) return TREE_STOP ;
-
- if (SetSignal(0, 0) & SIGBREAKF_CTRL_C) {
- errorflag = ERROR_BREAK ;
- return TREE_STOP ;
- }
-
- /* Start a new directory */
- if (fib == NULL) {
- /* flush path */
- pathname[0] = '\0' ;
- return TREE_CONT ;
- }
-
- /* See if we want to deal with this file */
- if (code) {
- lock_global = lock ;
- status = !execute(fib, code) ;
- if (filterstrings) {
- FreeRemember(&filterstrings, TRUE) ;
- filterstrings = NULL ;
- }
- if (status) return TREE_CONT ;
- }
-
- /* We do, so if we don't have it yet, get it's full name */
- if (!*pathname && getpathname(lock)) return TREE_STOP ;
-
- /* print it if nothing better to do */
- if (!*command) {
- printf("%s%s\n", pathname, fib->fib_FileName) ;
- return TREE_CONT ;
- }
-
- /* Deal with easy commands - just one argument! */
- if (singlearg) {
- growcommand("\"", FALSE) ;
- growcommand(pathname, FALSE) ;
- growcommand(fib->fib_FileName, FALSE) ;
- growcommand("\"", FALSE) ;
- docommand() ;
- return TREE_CONT ;
- }
-
- /* Otherwise, build up the command if we need to */
- if (commnext - command + strlen(pathname) + strlen(fib->fib_FileName) + 3 > COMMAX)
- docommand() ;
- growcommand("\"", FALSE) ;
- growcommand(pathname, FALSE) ;
- growcommand(fib->fib_FileName, FALSE) ;
- growcommand("\"", TRUE) ;
- return TREE_CONT ;
- }
-
- /*
- * And here we have things that check the global FIB, and extract values
- * from it.
- */
- long
- fibkey(struct FileInfoBlock *fib) {
- return fib->fib_DiskKey ;
- }
-
- long
- fibdirtype(struct FileInfoBlock *fib) {
- return fib->fib_DirEntryType ;
- }
-
- char *
- fibname(struct FileInfoBlock *fib) {
- char *tmpname ;
-
- if ((tmpname = AllocRemember(&filterstrings, 100, 0L)) == NULL) {
- fprintf(stderr, "%s: Out of memory\n", my_name) ;
- errorflag = ERROR_HALT ;
- return NULL ;
- }
- strcpy(tmpname, fib->fib_FileName) ;
- strlwr(tmpname) ;
- return tmpname ;
- }
-
- long
- fibprot(struct FileInfoBlock *fib) {
- return fib->fib_Protection ^ 017 ;
- }
-
- long
- fibtype(struct FileInfoBlock *fib) {
- return fib->fib_EntryType ;
- }
-
- long
- fibsize(struct FileInfoBlock *fib) {
- return fib->fib_Size ;
- }
-
- long
- fibblock(struct FileInfoBlock *fib) {
- return fib->fib_NumBlocks ;
- }
-
- long
- fibdate(struct FileInfoBlock *fib) {
- return fib->fib_Date.ds_Days * 24 * 60 + fib->fib_Date.ds_Minute ;
- }
-
- long
- fibday(struct FileInfoBlock *fib) {
- return fib->fib_Date.ds_Days * 24 * 60 ;
- }
-
- char *
- fibcomment(struct FileInfoBlock *fib) {
- char *tmpname ;
-
- if ((tmpname = AllocRemember(&filterstrings, 80, 0L)) == NULL) {
- fprintf(stderr, "%s: Out of memory\n", my_name) ;
- errorflag = ERROR_HALT ;
- return NULL ;
- }
- strcpy(tmpname, fib->fib_Comment) ;
- strlwr(tmpname) ;
- return tmpname ;
- }
-
- long
- askuser(struct FileInfoBlock *fib) {
- char c ;
-
- if (!*pathname && getpathname(lock_global)) return 1 ;
- fprintf(stderr, "%s%s? ", pathname, fib->fib_FileName) ;
- fflush(stderr) ;
- while ((c = getchar()) == ' ' || c == '\t')
- ;
- while (getchar() != '\n')
- ;
- return (long) (toupper(c) == 'Y') ;
- }
-
- char *
- fullname(struct FileInfoBlock *fib) {
- char *tmpname ;
-
- if ((tmpname = AllocRemember(&filterstrings, FMSIZE, 0L)) == NULL) {
- fprintf(stderr, "%s: Out of memory\n", my_name) ;
- errorflag = ERROR_HALT ;
- return NULL ;
- }
- if (!*pathname) getpathname(lock_global) ;
- strcpy(tmpname, pathname) ;
- strcat(tmpname, fib->fib_FileName) ;
- strlwr(tmpname) ;
- return tmpname ;
- }
-
- long
- isfile(struct FileInfoBlock *fib) {
- return (long) (fib->fib_DirEntryType < 0) ;
- }
-
- long
- isdir(struct FileInfoBlock *fib) {
- return (long) (fib->fib_DirEntryType >= 0) ;
- }
-
- /*
- * dofib - apply one of the fibfuncs to a named file.
- */
- long
- dofib(char *file, long (*func)(struct FileInfoBlock *)) {
- long lock, out ;
- struct FileInfoBlock *fib ;
-
- if ((fib = AllocMem(sizeof(struct FileInfoBlock), 0)) == NULL) {
- fprintf(stderr, "%s: Out of memory\n", my_name) ;
- errorflag = ERROR_HALT ;
- return 0 ;
- }
-
- if (!(lock = Lock(file, ACCESS_READ))) {
- fprintf(stderr, "%s: Can't lock %s\n", my_name, file) ;
- errorflag = ERROR_HALT ;
- FreeMem(fib, sizeof(*fib)) ;
- return 0 ;
- }
-
- lock_global = lock ;
- *pathname = '\0' ;
- if (!Examine(lock, fib)) {
- fprintf(stderr, "%s: Can't examine %s\n", my_name, file) ;
- errorflag = ERROR_HALT ;
- UnLock(lock) ;
- FreeMem(fib, sizeof(*fib)) ;
- return 0 ;
- }
-
- out = func(fib) ;
- UnLock(lock) ;
- FreeMem(fib, sizeof(*fib)) ;
- return out ;
- }
-
- #ifndef NO_REXX
- /*
- * Rexx interface - for now, just feed the routine to Rexx, and return
- * whatever integer it gives us back.
- */
- #include <rexx/rxslib.h>
- #include <rexx/storage.h>
- #include <exec/ports.h>
-
-
- struct Library *RexxSysBase = NULL ;
- #define REXXNAME "ftw"
-
- long
- dorexx(char *macro, struct FileInfoBlock *fib) {
- struct RexxMsg *msg ;
- struct MsgPort *rexxport, *port ;
- long out ;
- void *code ;
- char result[12] ;
-
- /* Get the library if we need it */
- if ((RexxSysBase = OpenLibrary("rexxsyslib.library", 0)) == NULL) {
- fprintf(stderr, "%s: Can't open rexx library\n", my_name) ;
- errorflag = ERROR_HALT ;
- return 0 ;
- }
-
- /* Create the port I use to talk to Rexx */
- Forbid() ;
- if (FindPort(REXXNAME) == NULL)
- port = CreatePort(REXXNAME, 0) ;
- Permit() ;
- if (port == NULL) {
- fprintf(stderr, "%s: Can't create port for rexx\n", my_name) ;
- goto badnews ;
- }
-
- /* Build the message to send */
- if ((msg = CreateRexxMsg(port, REXXNAME, port->mp_Node.ln_Name)) == NULL) {
- fprintf(stderr, "%s: Can't create rexx msg\n", my_name) ;
- goto badnews ;
- }
- msg->rm_Action = RXFUNC | RXFF_RESULT | 2 ;
-
- /* The command & two arguments */
- if (!*pathname) getpathname(lock_global) ;
- msg->rm_Args[0] = macro ;
- msg->rm_Args[1] = pathname ;
- msg->rm_Args[2] = fib->fib_FileName ;
- if (!FillRexxMsg(msg, 3, 0)) {
- fprintf(stderr, "%s: Can't create rexx arguments\n", my_name) ;
- DeleteRexxMsg(msg) ;
- goto badnews ;
- }
-
- /* send the message */
- Forbid() ;
- if (rexxport = FindPort(RXSDIR))
- PutMsg(rexxport, (struct Message *) msg) ;
- Permit() ;
- if (!rexxport) {
- fprintf(stderr, "%s: Can't find rexx port\n", my_name) ;
- goto badnews ;
- }
-
- /* Now, wait for it to come back to me */
- for (;;) {
- /* Get a message, and break if it's what I want */
- WaitPort(port) ;
- msg = (struct RexxMsg *) GetMsg(port) ;
- if (msg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG) break ;
-
- /*
- * Got a command - so we interpret the "command" as a filter,
- * and run it over the current fib.
- */
- if ((code = parse(msg->rm_Args[0])) == NULL) {
- /* Didn't parse - so return "broken command string" */
- msg->rm_Result1 = 10 ;
- msg->rm_Result2 = 11 ;
- }
- else {
- out = execute(fib, code) ;
- if (!(msg->rm_Action & RXFF_RESULT)) {
- /* Don't want results, so return TRUE/FALSE */
- msg->rm_Result1 = (out ? 0 : 1) ;
- msg->rm_Result2 = 0 ;
- }
- else { /* Want a result, so try and give it to them */
- sprintf(result, "%08lx", out) ;
- if ((msg->rm_Result2 =
- (LONG) CreateArgstring(result, (long) strlen(result)))
- != NULL)
- /* All ok, set result so */
- msg->rm_Result1 = 0 ;
- else {
- /* No memory, say so */
- msg->rm_Result1 = 20 ;
- msg->rm_Result2 = 3 ;
- }
- }
- }
- ReplyMsg((struct Message *) msg) ;
- }
-
- /* Check the result and do what must be done */
- if (msg->rm_Result1 == 0) {
- out = atoi((char *) msg->rm_Result2) ;
- DeleteArgstring((struct RexxArg *) msg->rm_Result2) ;
- }
- else {
- fprintf(stderr, "%s: Rexx error: %s\n", my_name,
- ErrorMsg(msg->rm_Result2)->ns_Buff) ;
- goto badnews ;
- }
-
- if (0) { /* Make sure we execute this iff we had a problem */
- badnews:
- errorflag = ERROR_HALT ;
- out = 0 ;
- }
-
- /* Clean up the port */
- if (port != NULL) {
- FreeSignal((long) (port->mp_SigBit)) ;
- RemPort(port) ;
- DeletePort(port) ;
- }
-
- /* Clean up the rexx msg */
- if (msg != NULL) {
- ClearRexxMsg(msg, 3) ;
- DeleteRexxMsg(msg) ;
- }
-
- /* Close the library, and return */
- if (RexxSysBase != NULL) CloseLibrary(RexxSysBase) ;
- return out ;
- }
- #endif
-