home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3970 < prev    next >
Encoding:
Text File  |  1991-09-05  |  7.5 KB  |  253 lines

  1. Path: wupost!uunet!mcsun!news.funet.fi!hydra!klaava!wirzeniu
  2. From: wirzeniu@klaava.Helsinki.FI (Lars Wirzenius)
  3. Newsgroups: alt.sources
  4. Subject: Unix-like CDPATH for MS-DOS
  5. Keywords: Unix-like CD CDPATH MS-DOS
  6. Message-ID: <1991Sep4.144301.11808@klaava.Helsinki.FI>
  7. Date: 4 Sep 91 14:43:01 GMT
  8. Followup-To: alt.sources.d
  9. Organization: University of Helsinki
  10. Lines: 241
  11.  
  12. An extract from the README:
  13.  
  14. This shar file contains two source files for as many programs: lacd.c
  15. and pwd.c. 
  16.  
  17. The lacd program emulates the CDPATH-feature of several Unix shells
  18. (i.e. the cd command prepends in turn each of the directories in the
  19. CDPATH environment variable and tries to go to the resulting directory;
  20. it stops as soon as it succeeds, of course). Read the beginning of the
  21. source file for a manual of sorts.
  22.  
  23. (...)
  24.  
  25. Bug reports, critique, suggestions for improvement and other feed back
  26. to wirzeniu@cc.helsinki.fi.
  27.  
  28. Lars Wirzenius
  29.  
  30.  
  31. #!/bin/sh
  32. #
  33. #  This is a shar file.  To use:
  34. #  1. Remove everything before the /bin/sh line
  35. #  2. Execute with /bin/sh (not csh) to extract the files:
  36. #         README
  37. #         lacd.c
  38. #         pwd.c
  39. #
  40. file="${0}"
  41. echo extracting README 1>&2
  42. sed 's/^X//' >README << 'EnD of README'
  43. XThis shar file contains two source files for as many programs: lacd.c
  44. Xand pwd.c. 
  45. X
  46. XThe lacd program emulates the CDPATH-feature of several Unix shells
  47. X(i.e. the cd command prepends in turn each of the directories in the
  48. XCDPATH environment variable and tries to go to the resulting directory;
  49. Xit stops as soon as it succeeds, of course). Read the beginning of the
  50. Xsource file for a manual of sorts.
  51. X
  52. XYou may be familiar with 'directory jumping' programs like NCD (Norton
  53. XCD, from the Norton Utilities), which build an auxiliary file with the
  54. Xcomplete directory tree. These have the drawback that the auxiliary
  55. Xfile needs to be updated (for many programs this means rebuilding) each
  56. Xtime the directory tree changes, which can be awkward if you often
  57. Xcreate directories from within several different programs, e.g.
  58. XPC-Tools, Windows and installation programs; it can also be slow.
  59. X
  60. XIf you use CED, 4DOS or something similar, you may want to create an
  61. Xalias cd that runs lacd instead the builtin command; that way you don't
  62. Xneed to learn any new keyboard reflexes. Except that you do: you can't
  63. Xjust use cd without arguments to get the current work directory (if
  64. Xyou're like me and don't use $p in your PROMPT). The pwd program is
  65. Xintended to remedy that: it prints the current work directory to the
  66. Xstandard output.
  67. X
  68. XBug reports, critique, suggestions for improvement and other feed back
  69. Xto wirzeniu@cc.helsinki.fi.
  70. X
  71. XLars Wirzenius
  72. EnD of README
  73. echo extracting lacd.c 1>&2
  74. sed 's/^X//' >lacd.c << 'EnD of lacd.c'
  75. X/*
  76. X * Name:    lacd.c
  77. X * Purpose:    Emulate the Unix cd command.
  78. X * Description:    If there are no arguments, go to the 'home' directory
  79. X *        (HOME or the root dir).
  80. X *        Otherwise, if the argument begins with a backslash or
  81. X *        dot or contains a drive, go to that directory.
  82. X *        Otherwise, go to first directory that can be found by
  83. X *        prepending a directory from CDPATH to the argument.
  84. X *        Otherwise, print an error message.
  85. X * Note:    HOME and CDPATH are environment variables. CDPATH consists
  86. X *        of directories that are separated by semicolons (';').
  87. X * Author:    Lars Wirzenius
  88. X * Version:    1.01
  89. X * Released:    1991-9-3 (aka September 3, 1991)
  90. X */
  91. X
  92. X#include <stdio.h>
  93. X#include <stdarg.h>
  94. X#include <string.h>
  95. X#include <stdlib.h>
  96. X#include <errno.h>
  97. X#include <ctype.h>
  98. X#include <dir.h>
  99. X
  100. Xchar cwd[MAXPATH];        /* Original work dir, restored on error.
  101. X                   This is a global variable, so it isn't
  102. X                   necessary to have _everyone_ know 
  103. X                   about it. Now only main and error do. */
  104. X
  105. Xint try(char *target);
  106. Xchar *egetenv(const char *env, const char *def);
  107. Xchar *cat_names(const char *prefix, const char *suffix);
  108. Xvoid error(const char *fmt, ...);
  109. X
  110. Xint main(int argc, char **argv) {
  111. X    char *p, *q, *cdpath, *home, *arg, *buf;
  112. X    int ok;
  113. X
  114. X    /* Save current work directory */
  115. X    if (getcwd(cwd, sizeof(cwd)) == NULL) {
  116. X        cwd[0] = '\0';        /* error needs _something_ in cwd */
  117. X        error("Can't find the name of the current directory!\n");
  118. X    }
  119. X
  120. X    arg = (argc == 1 || argv[1][0] == '\0') ? NULL : argv[1];
  121. X    cdpath = egetenv("CDPATH", NULL);
  122. X    home = egetenv("HOME", "\\");
  123. X
  124. X    if (arg == NULL)
  125. X        ok = try(home);
  126. X    else if (arg[0] == '\\' || arg[1] == ':' || arg[0] == '.'
  127. X                 || cdpath == NULL)
  128. X        ok = try(arg);
  129. X    else {
  130. X        /* Can't use strtok to separate parts of CDPATH, since
  131. X           strtok won't return empty string for ";;". */
  132. X        q = cdpath;
  133. X        do {
  134. X            p = q;
  135. X            if ((q = strchr(q, ';')) != NULL) {
  136. X                *q = '\0';    /* ok to modify, it's a copy, 
  137. X                           not the original */
  138. X                ++q;
  139. X            }
  140. X            buf = cat_names(p, arg);
  141. X            ok = try(buf);
  142. X            if (ok && strcmp(p, ".") != 0 && *p != '\0')
  143. X                printf("%s\n", buf);
  144. X        } while (!ok && q != NULL);
  145. X    }
  146. X
  147. X    if (!ok)
  148. X        error("I'm lost, can't find anywhere to go\n");
  149. X    if (fflush(stdout) != 0 || ferror(stdout))
  150. X        error("Output error\n");
  151. X
  152. X    free(cdpath);
  153. X    free(home);
  154. X        
  155. X    exit(EXIT_SUCCESS);
  156. X}
  157. X
  158. X
  159. X/* Try to go to directory given as argument, return 0 for failure, nonzero
  160. X   for success. */
  161. Xint try(char *p) {
  162. X    if (p[0] != '\0' && p[1] == ':')
  163. X        setdisk(toupper(*p) - 'A');    /* no error return */
  164. X    return chdir(p) == 0;
  165. X}
  166. X
  167. X
  168. X/* If the environment variable env exists, make copy of it, else make copy
  169. X   of def. Abort program if copying fails, else return pointer to copy. */
  170. Xchar *egetenv(const char *env, const char *def) {
  171. X    const char *p;
  172. X
  173. X    if ((p = getenv(env)) == NULL)
  174. X        p = def;
  175. X    if (p != NULL && (p = strdup(p)) == NULL)
  176. X        error("Out of memory?\n");
  177. X    return (char *) p;    /* p is NULL or points to memory from
  178. X                   strdup, so conversion is OK */
  179. X}
  180. X
  181. X
  182. X
  183. X/* Concatenate prefix and suffix into a complete directory name into
  184. X   static buffer, which may move (i.e., a previous return value may no
  185. X   longer be valid after a new call) and is overwritten at each call */
  186. Xchar *cat_names(const char *prefix, const char *suffix) {
  187. X    static char *buf = NULL;
  188. X    static size_t size = 0;
  189. X    const char *sep;
  190. X    const char *p;
  191. X    size_t newsize;
  192. X
  193. X    if ((p = strchr(prefix, '\0')) > prefix)
  194. X        --p;
  195. X    sep = (*p == '\\' || *p == '\0') ? "" : "\\";
  196. X    newsize = strlen(prefix) + strlen(sep) + strlen(suffix) + 1;
  197. X    if (newsize > size) {
  198. X        if ((buf = (char *) realloc(buf, newsize)) == NULL)
  199. X            error("Out of memory? Can't continue, sorry.\n");
  200. X        size = newsize;
  201. X    }        
  202. X    sprintf(buf, "%s%s%s", prefix, sep, suffix);
  203. X    return buf;
  204. X}
  205. X
  206. X
  207. X/* Print error message, try to restore cwd, and commit suicide. */
  208. Xvoid error(const char *fmt, ...) {
  209. X    va_list args;
  210. X
  211. X    if (errno != 0)
  212. X        perror("lacd");
  213. X    va_start(args, fmt);
  214. X    (void) vfprintf(stderr, fmt, args);
  215. X        /* If it doesn't work, then it doesn't work and there's 
  216. X           nothing we can do about it, so we'll ignore any error 
  217. X           code vfprintf may return. */
  218. X    va_end(args);
  219. X
  220. X    if (cwd != '\0' && !try(cwd))
  221. X        (void) fprintf(stderr, "Couldn't go back to %s!\n", cwd);
  222. X
  223. X    exit(EXIT_FAILURE);
  224. X}
  225. EnD of lacd.c
  226. echo extracting pwd.c 1>&2
  227. sed 's/^X//' >pwd.c << 'EnD of pwd.c'
  228. X/*
  229. X * Name:    pwd.c
  230. X * Purpose:    Print the current working directory to stdout
  231. X * Author:    Lars Wirzenius
  232. X * Version:    1.00
  233. X * Released:    1991-9-3 (aka September 3, 1991)
  234. X */
  235. X
  236. X#include <stdio.h>
  237. X#include <stdlib.h>
  238. X#include <dir.h>
  239. X
  240. Xint main(void) {
  241. X    char buf[MAXPATH];
  242. X
  243. X    if (getcwd(buf, sizeof(buf)) == NULL) {
  244. X        perror("pwd: getcwd");
  245. X        exit(EXIT_FAILURE);
  246. X    }
  247. X    puts(buf);
  248. X    exit(EXIT_SUCCESS);
  249. X}
  250. EnD of pwd.c
  251. -- 
  252. Lars Wirzenius     wirzeniu@cc.helsinki.fi
  253.