home *** CD-ROM | disk | FTP | other *** search
- /*
- * ccd.c
- */
-
- /* $Id: ccd.c,v 1.24 1993/07/03 18:41:52 beust Exp $ */
-
- static char __version[] = "\0$VER: ccd 3.2 (03-Jul-93)";
-
- #define EXTRAHELP "ccd 3.2, by Cédric BEUST (beust@sophia.inria.fr) $Date: 03-Jul-93\n\n"
-
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <proto/dos.h>
- #include <proto/intuition.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <libraries/amigaguide.h>
- #include <intuition/intuition.h>
- #include <clib/dos_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/graphics_protos.h>
- #include <clib/amigaguide_protos.h>
-
- #include "ccd.h"
-
- #define GRAPHICS
-
- #define min(a,b) (a < b ? a : b)
-
- #ifndef NEW
- #define NEW(v, t) v = (t *) malloc(sizeof(*v))
- #endif
-
- #define D(x) x
-
- #define IntuitionBase gv -> IntuitionBase
-
- /****************************************************************************/
- /* Private functions */
- /****************************************************************************/
-
- static Entry
- locateDir(struct GlobalVars *gv, char *dir, DataBase db, BOOL partial)
- /* Return the path for the fragment given, if any, in database. partial */
- /* is true if only the partial dir must be returned */
- {
- Entry result = NULL, entry = NULL;
- int match = 0;
- char *p, *onedir, pat1[128], pat3[128];
- char p1[300], p3[300];
-
- sprintf(pat1, "#?(/|:)%s(/|)", dir);
- sprintf(pat3, "#?%s#?", dir);
- ParsePatternNoCase(pat1, p1, 300);
- ParsePatternNoCase(pat3, p3, 300);
- /* Give priority to "exact matches" (e.g. DH0:l instead of DH0:Applications) */
- /* match = 1 if approximate match, 2 if exact match */
- while (! DB_EndOfDataBase(db) && match != 2) {
- int i;
- entry = DB_NextEntry(db);
- p = entry -> fullPath;
- if (MatchPatternNoCase(p1, p)) {
- match = 2;
- result = entry;
- }
- else if (MatchPatternNoCase(p3, p)) {
- match = (partial ? 2 : 1);
- result = entry;
- }
- }
-
- return result;
- }
-
- static BPTR
- getLock(struct GlobalVars *gv, char *name, long code)
- {
- BPTR *locklist = gv -> lockList;
- int lockpt = gv -> lockpt;
-
- locklist[lockpt] = Lock(name, code);
- if (locklist[lockpt])
- return locklist[lockpt++];
- else
- return 0;
- }
-
- static void
- unlock(BPTR lock)
- {
- /*
- UnLock(lock);
- */
- }
-
- /*
- static void
- freeAllLocks()
- {
- int i;
- for (i = 0; i < lockpt; i++)
- UnLock(locklist[i]);
- }
- */
-
- static char *
- reverse(char *s)
- /* Return the string s backwards (modify s)*/
- {
- register char c;
- char *result = s + strlen(s) - 1, *r2 = s;
-
- while (result > s) {
- c = *result;
- *result = *s;
- *s = c;
- s++; result--;
- }
- return(r2);
- }
-
- #ifdef A
- int
- mystricmp(char *bigdir, char *shortdir)
- /* Check if shortdir is part of the path bigdir, return 0 if it is */
- {
- char t[50], *pt = t, *ps;
- int i = 0;
-
- while (*bigdir) {
- while (*bigdir && *bigdir != ':' && *bigdir != '/' && *bigdir != '\n')
- *pt++ = *bigdir++;
- if (*bigdir) bigdir++;
- *pt++ = '\0';
- pt = t;
- }
-
- /* Now, we must see if shortdir is included in t */
-
- for (i = 0; i <= strlen(t) - strlen(shortdir); i++) {
- pt = &t[i]; ps = shortdir;
- while (*pt && *ps && (*pt | 0x20) == (*ps | 0x20)) {
- ps++; pt++;
- };
- if (*pt == 0 || *ps == 0) return(0); /* match! */
- }
- return(1);
- }
- #endif
-
- static void
- myputs(char *s)
- {
- Write(Output(), s, strlen(s));
- }
-
-
- static void
- readDirs(char *dir, FILE *f)
- {
- BPTR lock;
- struct FileInfoBlock info, *fib;
-
- lock = Lock(dir, ACCESS_READ);
- if (lock == 0) {
- fprintf(stderr,"*** Yup! Couldn't lock %s\n", dir);
- return;
- }
-
- fib = (struct FileInfoBlock *) Examine(lock, &info);
- fib = &info;
- while (1) {
- if (ExNext(lock, fib) == 0) break;
- if (fib -> fib_DirEntryType > 0) {
- char t[50],c;
- strcpy(t, dir);
- if ((c = t[strlen(t) - 1]) != ':' && c != '/')
- strcat(t,"/");
- strcat(t, fib -> fib_FileName);
- fprintf(f, "%s\n", t);
- readDirs(t,f);
- }
- }
- unlock(lock);
- }
-
-
- static int
- writeConfigFile(struct GlobalVars *gv, char **dirname, int ndirs, char *mode)
- /* Update the config file with the list of dirs (dirname) of length ndirs */
- {
- char *file = gv -> prefs.configFile;
- FILE *f = fopen(file, mode);
- char *tempFile = "t:.cdconfig.unsorted";
- char command[128];
- int i;
-
- if (f == NULL) {
- fprintf(stderr, "*** Couldn't open '%s (%s)', maybe an assign is missing?\n",
- file, mode);
- return(0);
- }
- printf("%s with", file);
- for (i = 0; i < ndirs; i++) {
- printf(" %s", *dirname);
- fflush(stdout);
- fprintf(f, "%s\n", *dirname);
- readDirs(*dirname++, f);
- }
- printf(" -- done!\n");
- fclose(f);
-
-
- sprintf(command, "copy %s %s", file, tempFile);
- if (SystemTags(command, TAG_DONE) == 0) {
- DeleteFile(file);
- sprintf(command, "sort %s %s", tempFile, file);
- if (SystemTags(command, TAG_DONE) != 0) {
- fprintf(stderr, "*** couldn't sort %s %s\n", tempFile, file);
- sprintf(command, "copy %s %s", tempFile, file);
- }
- }
- else {
- fprintf(stderr, "*** couldn't copy %s to %s\n", file, tempFile);
- }
- }
-
- /****************************************************************************/
- /* Public functions */
- /****************************************************************************/
-
- int
- updateConfigFile(struct GlobalVars *gv, char **dirname, int ndirs)
- {
- printf("Updating ");
- return writeConfigFile(gv, dirname, ndirs, "a");
- }
-
- int
- createConfigFile(struct GlobalVars *gv, char **dirname, int ndirs)
- {
- printf("Creating ");
- return writeConfigFile(gv, dirname, ndirs, "w");
- }
-
-
- void
- updatePrompt(char *currentdir)
- /* Update the concerned field with the new current dir */
- /* This routine is for users of wshell or such, thar display this name */
- /* as the shell prompt. */
- /* This trick was previously pointed to me by Henry J. Cobb on Usenet */
- /* for my 'find' program (another great utility of mine :-)). */
- /* Let him be thanked again! */
- {
- struct Process *pr = (struct Process *) FindTask(0L);
- struct CommandLineInterface *cli = (struct CommandLineInterface *) pr -> pr_CLI;
- char *p;
- int n;
-
- n = (int) cli;
- n = n << 2;
- cli = (struct CommandLineInterface *) n;
-
- n = (int) cli -> cli_SetName;
- n = n << 2;
- p = (char *) n;
-
- *p++ = strlen(currentdir); /* it is a BSTR, so length first */
- while (*currentdir) *p++ = *currentdir++; /* don't add '\0' */
- }
-
- #ifdef A
- void
- getRealName(struct GlobalVars *gv, BPTR lock, char *result)
- /* This is a very useful function! Put in result path of lock */
- /* Assume lock is not null */
- /* Result always device:dir/dir/... */
- {
- char *p = result;
- struct FileInfoBlock ib;
-
- assert(lock);
-
- if (gv -> prefs.noExpand) return;
- Examine(lock, &ib);
- strcpy(result, reverse(ib.fib_FileName));
- strcat(result, "/");
- while (lock) {
- lock = ParentDir(lock);
- if (lock) {
- Examine(lock, &ib);
- strcat(result, reverse(ib.fib_FileName));
- strcat(result,"/");
- unlock(lock);
- }
- }
- p = &p[strlen(p) - 1];
- *p-- = '\0';
- while (*p != '/') p--;
- *p = ':';
- reverse(result);
- }
- #endif
-
- void
- changeDir(struct GlobalVars *gv, char *dir, int occ)
- /* The main function to change to the fragment of dir given, */
- /* to the occ'th (first = 1) occurence found in the config file */
- /* New 1.3: first, try to cd right into 'dir' */
- {
- char actualdir[256];
- BPTR lock;
-
- DB_Rewind(gv -> db);
-
- strcpy(actualdir, dir);
- if ((lock = Lock(actualdir, ACCESS_READ))) { /* can we cd directly? */
- BPTR old;
- NameFromLock(lock, actualdir, 256);
- lock = getLock(gv, actualdir, ACCESS_READ);
- if (gv -> prefs.verbose)
- printf("Current directory is now %s\n", actualdir);
- SetCurrentDirName(actualdir);
- old = CurrentDir(lock); /* yes! Do it and end */
- /*
- UnLock(lock);
- UnLock(old);
- */
- return;
- }
-
- /* no, dir is a path fragment */
- while (occ--) {
- Entry entry = locateDir(gv, dir, gv -> db, TRUE);
- strcpy(actualdir, entry -> fullPath);
- }
-
- if (actualdir[0]) {
- lock = Lock(actualdir, ACCESS_READ);
- if (lock == 0) {
- fprintf(stderr,
- "*** Couldn't cd to %s, '%s' probably outdated (re-run ccd create)\n",
- actualdir, gv -> prefs.configFile);
- exit(0);
- }
- if (gv -> prefs.noExpand)
- strcpy(actualdir, dir);
- else
- NameFromLock(lock, actualdir, 256);
- /*
- getRealName(gv, lock, actualdir);
- */
- if (gv -> prefs.verbose)
- printf("Current directory is now %s\n", actualdir);
- CurrentDir(lock);
- SetCurrentDirName(actualdir);
- /*
- updatePrompt(actualdir);
- */
- unlock(lock);
- }
- else
- printf("%s: no such dir\n", dir);
- }
-
- void
- showAmbiguities(struct GlobalVars *gv, char *dir)
- {
- Entry entry;
-
- DB_Rewind(gv -> db);
- while ((entry = locateDir(gv, dir, gv -> db, TRUE))) {
- myputs(entry -> fullPath);
- myputs("\n");
- }
-
- }
-
- void
- nthdir(char *dir, char *path, int n)
- /* Path is 'volume:a/b/c' */
- /* Return in dir the nth dir in it (e.g. with n=2, it's b) */
- {
- char *dirhead = dir;
- while (*path && *path != ':') path++;
- if (*path == ':') {
- path++;
- while (*path) {
- while (*path && *path != '/') {
- *dir++ = *path++;
- }
- if (*(dir - 1) == '\n') dir--;
- *dir++ = '\0';
- if (*path == '/') path++;
- if (n == 1) return;
- else {
- n--; dir = dirhead;
- }
- }
- }
- else {
- printf("nthdir: problem\n");
- exit(0);
- }
- }
-
-
- static void
- freeEntry(Entry entry)
- {
- free(entry -> name);
- }
-
- static int
- countCharsInString(char *s, char *set)
- /* Return number of occurences of the chars in set in string s */
- {
- int result = 0;
- while (*s) {
- if (stpchr(set, *s)) result++;
- /*
- char *p = set;
- while (*p) {
- if (*s == *p++) result++;
- }
- */
- s++;
- }
-
- return result;
- }
-
- static int
- pathParts(char *dir)
- /* Return # of path parts (e.g. ram: -> 1, ram:env -> 2, ram:env/s -> 3 */
- {
- int result = countCharsInString(dir, ":/");
- if (strcmp(PathPart(dir), "")) result++;
-
- return result;
- }
-
- static int
- returnNextLine(struct GlobalVars *gv, FILE *f, char *buffer, int size)
- {
- int result = 0, i;
-
- if (feof(f))
- result = 0;
- else {
- fgets(buffer, size, f);
- i = strlen(buffer) - 1;
- if (buffer[i] == '\n')
- buffer[i] = '\0'; /* strip trailing \n */
- result = i;
- }
-
- return result;
- }
-
- static void
- buildAntiDataBase(struct GlobalVars *gv)
- /* Build the anti database (if the file exists) */
- {
- FILE *f = fopen(gv -> prefs.antiConfigFile, "r");
- int l = 1;
- char line[256];
- DataBase db;
- struct _Entry entry;
-
- if (f) {
- gv -> antidb = db = DB_NewDataBase(sizeof(struct _Entry), freeEntry);
- while (returnNextLine(gv, f, line, 256)) {
- entry.spaces = "";
- entry.name = entry.fullPath = strdup(line);
- entry.line = l++;
- DB_AddEntry(db, & entry);
- }
- fclose(f);
- }
- }
-
- static BOOL
- isDirectoryBelow(char *dir1, char *dir2)
- /* Is dir2 below dir1? */
- {
- BOOL result;
-
- if (strlen(dir1) == 0) result = FALSE;
- else {
- if (strnicmp(dir1, dir2, strlen(dir1)) == 0)
- result = TRUE;
- else
- result = FALSE;
- }
-
- return result;
- }
-
- static int
- buildMainDataBase(struct GlobalVars *gv, DataBase db)
- {
- int result = 0, line = 1, n;
- static char onedir[256], spaces[256], fullLine[256];
- FILE *f = fopen(gv -> prefs.configFile, "r");
- struct _Entry entry;
- int i;
-
-
- buildAntiDataBase(gv);
- if (f == NULL) {
- fprintf(stderr, "*** couldn't open '%s'\n", gv -> prefs.configFile);
- result = 1;
- }
- else {
- BOOL skip = NULL;
- while (returnNextLine(gv, f, onedir, 256)) {
- if (gv -> antidb) {
- DataBase adb = gv -> antidb;
- Entry anti;
- DB_Rewind(adb);
- skip = FALSE;
- while (! DB_EndOfDataBase(adb) && ! skip) {
- anti = DB_NextEntry(adb);
- if (isDirectoryBelow(anti -> name, onedir)) {
- skip = TRUE;
- }
- }
- }
-
- if (! skip) {
- n = pathParts(onedir);
- strcpy(spaces, "");
- for (i=0; i<n; i++) strcat(spaces, " ");
- sprintf(fullLine, "%s%s", spaces, onedir);
- entry.spaces = strdup(spaces);
- entry.fullPath = strdup(onedir);
- entry.name = strdup(n == 1 ? onedir : (char *) FilePart(onedir));
- entry.line = line++;
- DB_AddEntry(db, & entry);
- }
- }
- fclose(f);
- }
-
- return result;
-
- }
-
- static DataBase
- buildAmbiguitiesDataBase(struct GlobalVars *gv, char *dir)
- /* Build a database made of ambiguities only */
- {
- int line = 1;
- char *fullPath;
- DataBase gdb = gv -> db, result;
- struct _Entry entry, *entry2;
-
- result = DB_NewDataBase(sizeof(struct _Entry), freeEntry);
- DB_Rewind(gdb);
- while (entry2 = locateDir(gv, dir, gdb, TRUE)) {
- entry.fullPath = strdup(entry2 -> fullPath);
- entry.name = entry.fullPath;
- entry.spaces = ""; /* no spaces displayed when displaying ambiguities */
- entry.line = line++;
- DB_AddEntry(result, & entry);
- }
-
- return result;
- }
-
- void
- readEnvironment(struct GlobalVars *gv, int argc, char **argv)
- {
- struct CSource cs;
- struct RDArgs rda, *rda2;
- struct Prefs result;
-
- memset(& result, 0, sizeof(result));
- gv -> prefs.configFile = CCD_FILE_DEFAULT_CONFIG;
- gv -> prefs.antiConfigFile = CCD_FILE_DEFAULT_ANTI_CONFIG;
-
- if (argc) { /* called from CLI */
- memset(& rda, 0, sizeof(rda));
- rda.RDA_ExtHelp = EXTRAHELP;
- rda2 = ReadArgs(gv -> usage, (LONG *) & result, & rda);
- if (rda2 == NULL)
- fprintf(stderr, "Erreur: %s\n", gv -> usage);
-
- /* We have to copy any returned value, its reference is not safe */
- if (result.noExpand) gv -> prefs.noExpand = TRUE;
- if (result.showAmbiguities) gv -> prefs.showAmbiguities = TRUE;
- if (result.update) gv -> prefs.update = TRUE;
- if (result.create) gv -> prefs.create = TRUE;
- if (result.gui) gv -> prefs.gui = TRUE;
- if (result.verbose) gv -> prefs.verbose = TRUE;
- if (result.dirs) {
- char **p = result.dirs;
- int i=0;
- while (p[i]) i++;
- gv -> prefs.dirs = (char **) malloc(sizeof(char *) * i);
- i = 0;
- p = result.dirs;
- while (p[i]) {
- gv -> prefs.dirs[i] = strdup(p[i]); i++;
- }
- gv -> dirCount = i;
-
- }
-
- FreeArgs(rda2);
- }
- }
-
- int
- main(int argc, char **argv)
- {
- struct GlobalVars gv;
- struct Prefs prefs;
- int i = 1, line = 1;
- char *dir = NULL;
-
- memset(& gv, 0, sizeof(gv));
- gv.usage = "Create=-c/S,Update=u/S,ConfigFile=-cf/K,AntiConfigFile=-acf/K,Noexpand=-b/S,ShowAmbiguities=-s/S,GUI=-g/S,Verbose=-v/S,Dirs/M";
- gv.actualLine = 1;
-
- readEnvironment(& gv, argc, argv);
- prefs = gv.prefs;
- if (prefs.dirs)
- dir = prefs.dirs[0];
-
- if (prefs.create || prefs.update || prefs.noExpand ||
- prefs.showAmbiguities || prefs.gui || dir) { /* shortcut */
- gv.db = DB_NewDataBase(sizeof(struct _Entry), freeEntry);
- buildMainDataBase(& gv, gv.db);
- }
-
- if (prefs.gui) {
- char var[128];
- DataBase db = gv.db;
- if (prefs.showAmbiguities && dir) {
- db = buildAmbiguitiesDataBase(& gv, dir);
- }
-
- DeleteVar(CCD_VAR_LAST_DIR, GVF_GLOBAL_ONLY);
- displayTree(& gv, db);
- if (GetVar(CCD_VAR_LAST_DIR, var, 128, GVF_GLOBAL_ONLY) == -1)
- fprintf(stderr, "Aborted\n");
- else {
- changeDir(& gv, var, 1);
- }
- }
-
- else if (prefs.update) {
- updateConfigFile(& gv, prefs.dirs, gv.dirCount);
- }
-
- else if (prefs.create) {
- createConfigFile(& gv, prefs.dirs, gv.dirCount);
- }
-
- else if (prefs.showAmbiguities) {
- char *var = dir;
- if (! var) {
- fprintf(stderr, "You must specify a directory to change to\nAborted\n");
- }
- else {
- int n = 1;
- if (isdigit(prefs.dirs[1][0])) { /* an occurence was given */
- n = atoi(prefs.dirs[1]);
- changeDir(& gv, var, n);
- }
- else
- showAmbiguities(& gv, var);
- }
- }
- else if (!prefs.gui && dir == NULL) {
- char currentDir[256];
- GetCurrentDirName(currentDir, 256);
- printf("%s\n", currentDir);
- }
- else {
- char *var = dir;
- changeDir(& gv, var, 1);
- if (SetVar(CCD_VAR_LAST_DIR, var, strlen(var), GVF_GLOBAL_ONLY) == 0) {
- BPTR lock;
- lock = CreateDir("ENV:CCD");
- if (SetVar(CCD_VAR_LAST_DIR, var, strlen(var), GVF_GLOBAL_ONLY) == 0) {
- fprintf(stderr, "*** couldn't set variable %s\n", CCD_VAR_LAST_DIR);
- }
- }
- }
- return 0;
- }
-