home *** CD-ROM | disk | FTP | other *** search
- Path: wupost!uunet!mcsun!news.funet.fi!hydra!klaava!wirzeniu
- From: wirzeniu@klaava.Helsinki.FI (Lars Wirzenius)
- Newsgroups: alt.sources
- Subject: Unix-like CDPATH for MS-DOS
- Keywords: Unix-like CD CDPATH MS-DOS
- Message-ID: <1991Sep4.144301.11808@klaava.Helsinki.FI>
- Date: 4 Sep 91 14:43:01 GMT
- Followup-To: alt.sources.d
- Organization: University of Helsinki
- Lines: 241
-
- An extract from the README:
-
- This shar file contains two source files for as many programs: lacd.c
- and pwd.c.
-
- The lacd program emulates the CDPATH-feature of several Unix shells
- (i.e. the cd command prepends in turn each of the directories in the
- CDPATH environment variable and tries to go to the resulting directory;
- it stops as soon as it succeeds, of course). Read the beginning of the
- source file for a manual of sorts.
-
- (...)
-
- Bug reports, critique, suggestions for improvement and other feed back
- to wirzeniu@cc.helsinki.fi.
-
- Lars Wirzenius
-
-
- #!/bin/sh
- #
- # This is a shar file. To use:
- # 1. Remove everything before the /bin/sh line
- # 2. Execute with /bin/sh (not csh) to extract the files:
- # README
- # lacd.c
- # pwd.c
- #
- file="${0}"
- echo extracting README 1>&2
- sed 's/^X//' >README << 'EnD of README'
- XThis shar file contains two source files for as many programs: lacd.c
- Xand pwd.c.
- X
- XThe lacd program emulates the CDPATH-feature of several Unix shells
- X(i.e. the cd command prepends in turn each of the directories in the
- XCDPATH environment variable and tries to go to the resulting directory;
- Xit stops as soon as it succeeds, of course). Read the beginning of the
- Xsource file for a manual of sorts.
- X
- XYou may be familiar with 'directory jumping' programs like NCD (Norton
- XCD, from the Norton Utilities), which build an auxiliary file with the
- Xcomplete directory tree. These have the drawback that the auxiliary
- Xfile needs to be updated (for many programs this means rebuilding) each
- Xtime the directory tree changes, which can be awkward if you often
- Xcreate directories from within several different programs, e.g.
- XPC-Tools, Windows and installation programs; it can also be slow.
- X
- XIf you use CED, 4DOS or something similar, you may want to create an
- Xalias cd that runs lacd instead the builtin command; that way you don't
- Xneed to learn any new keyboard reflexes. Except that you do: you can't
- Xjust use cd without arguments to get the current work directory (if
- Xyou're like me and don't use $p in your PROMPT). The pwd program is
- Xintended to remedy that: it prints the current work directory to the
- Xstandard output.
- X
- XBug reports, critique, suggestions for improvement and other feed back
- Xto wirzeniu@cc.helsinki.fi.
- X
- XLars Wirzenius
- EnD of README
- echo extracting lacd.c 1>&2
- sed 's/^X//' >lacd.c << 'EnD of lacd.c'
- X/*
- X * Name: lacd.c
- X * Purpose: Emulate the Unix cd command.
- X * Description: If there are no arguments, go to the 'home' directory
- X * (HOME or the root dir).
- X * Otherwise, if the argument begins with a backslash or
- X * dot or contains a drive, go to that directory.
- X * Otherwise, go to first directory that can be found by
- X * prepending a directory from CDPATH to the argument.
- X * Otherwise, print an error message.
- X * Note: HOME and CDPATH are environment variables. CDPATH consists
- X * of directories that are separated by semicolons (';').
- X * Author: Lars Wirzenius
- X * Version: 1.01
- X * Released: 1991-9-3 (aka September 3, 1991)
- X */
- X
- X#include <stdio.h>
- X#include <stdarg.h>
- X#include <string.h>
- X#include <stdlib.h>
- X#include <errno.h>
- X#include <ctype.h>
- X#include <dir.h>
- X
- Xchar cwd[MAXPATH]; /* Original work dir, restored on error.
- X This is a global variable, so it isn't
- X necessary to have _everyone_ know
- X about it. Now only main and error do. */
- X
- Xint try(char *target);
- Xchar *egetenv(const char *env, const char *def);
- Xchar *cat_names(const char *prefix, const char *suffix);
- Xvoid error(const char *fmt, ...);
- X
- Xint main(int argc, char **argv) {
- X char *p, *q, *cdpath, *home, *arg, *buf;
- X int ok;
- X
- X /* Save current work directory */
- X if (getcwd(cwd, sizeof(cwd)) == NULL) {
- X cwd[0] = '\0'; /* error needs _something_ in cwd */
- X error("Can't find the name of the current directory!\n");
- X }
- X
- X arg = (argc == 1 || argv[1][0] == '\0') ? NULL : argv[1];
- X cdpath = egetenv("CDPATH", NULL);
- X home = egetenv("HOME", "\\");
- X
- X if (arg == NULL)
- X ok = try(home);
- X else if (arg[0] == '\\' || arg[1] == ':' || arg[0] == '.'
- X || cdpath == NULL)
- X ok = try(arg);
- X else {
- X /* Can't use strtok to separate parts of CDPATH, since
- X strtok won't return empty string for ";;". */
- X q = cdpath;
- X do {
- X p = q;
- X if ((q = strchr(q, ';')) != NULL) {
- X *q = '\0'; /* ok to modify, it's a copy,
- X not the original */
- X ++q;
- X }
- X buf = cat_names(p, arg);
- X ok = try(buf);
- X if (ok && strcmp(p, ".") != 0 && *p != '\0')
- X printf("%s\n", buf);
- X } while (!ok && q != NULL);
- X }
- X
- X if (!ok)
- X error("I'm lost, can't find anywhere to go\n");
- X if (fflush(stdout) != 0 || ferror(stdout))
- X error("Output error\n");
- X
- X free(cdpath);
- X free(home);
- X
- X exit(EXIT_SUCCESS);
- X}
- X
- X
- X/* Try to go to directory given as argument, return 0 for failure, nonzero
- X for success. */
- Xint try(char *p) {
- X if (p[0] != '\0' && p[1] == ':')
- X setdisk(toupper(*p) - 'A'); /* no error return */
- X return chdir(p) == 0;
- X}
- X
- X
- X/* If the environment variable env exists, make copy of it, else make copy
- X of def. Abort program if copying fails, else return pointer to copy. */
- Xchar *egetenv(const char *env, const char *def) {
- X const char *p;
- X
- X if ((p = getenv(env)) == NULL)
- X p = def;
- X if (p != NULL && (p = strdup(p)) == NULL)
- X error("Out of memory?\n");
- X return (char *) p; /* p is NULL or points to memory from
- X strdup, so conversion is OK */
- X}
- X
- X
- X
- X/* Concatenate prefix and suffix into a complete directory name into
- X static buffer, which may move (i.e., a previous return value may no
- X longer be valid after a new call) and is overwritten at each call */
- Xchar *cat_names(const char *prefix, const char *suffix) {
- X static char *buf = NULL;
- X static size_t size = 0;
- X const char *sep;
- X const char *p;
- X size_t newsize;
- X
- X if ((p = strchr(prefix, '\0')) > prefix)
- X --p;
- X sep = (*p == '\\' || *p == '\0') ? "" : "\\";
- X newsize = strlen(prefix) + strlen(sep) + strlen(suffix) + 1;
- X if (newsize > size) {
- X if ((buf = (char *) realloc(buf, newsize)) == NULL)
- X error("Out of memory? Can't continue, sorry.\n");
- X size = newsize;
- X }
- X sprintf(buf, "%s%s%s", prefix, sep, suffix);
- X return buf;
- X}
- X
- X
- X/* Print error message, try to restore cwd, and commit suicide. */
- Xvoid error(const char *fmt, ...) {
- X va_list args;
- X
- X if (errno != 0)
- X perror("lacd");
- X va_start(args, fmt);
- X (void) vfprintf(stderr, fmt, args);
- X /* If it doesn't work, then it doesn't work and there's
- X nothing we can do about it, so we'll ignore any error
- X code vfprintf may return. */
- X va_end(args);
- X
- X if (cwd != '\0' && !try(cwd))
- X (void) fprintf(stderr, "Couldn't go back to %s!\n", cwd);
- X
- X exit(EXIT_FAILURE);
- X}
- EnD of lacd.c
- echo extracting pwd.c 1>&2
- sed 's/^X//' >pwd.c << 'EnD of pwd.c'
- X/*
- X * Name: pwd.c
- X * Purpose: Print the current working directory to stdout
- X * Author: Lars Wirzenius
- X * Version: 1.00
- X * Released: 1991-9-3 (aka September 3, 1991)
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <dir.h>
- X
- Xint main(void) {
- X char buf[MAXPATH];
- X
- X if (getcwd(buf, sizeof(buf)) == NULL) {
- X perror("pwd: getcwd");
- X exit(EXIT_FAILURE);
- X }
- X puts(buf);
- X exit(EXIT_SUCCESS);
- X}
- EnD of pwd.c
- --
- Lars Wirzenius wirzeniu@cc.helsinki.fi
-