home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / ex / ex_cd.c < prev    next >
Text File  |  1997-06-24  |  4KB  |  154 lines

  1. /*-
  2.  * Copyright (c) 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  * Copyright (c) 1992, 1993, 1994, 1995, 1996
  5.  *    Keith Bostic.  All rights reserved.
  6.  *
  7.  * See the LICENSE file for redistribution information.
  8.  */
  9.  
  10. #include "config.h"
  11.  
  12. #ifndef lint
  13. static const char sccsid[] = "@(#)ex_cd.c    10.10 (Berkeley) 8/12/96";
  14. #endif /* not lint */
  15.  
  16. #include <sys/param.h>
  17. #include <sys/queue.h>
  18.  
  19. #include <bitstring.h>
  20. #include <errno.h>
  21. #include <limits.h>
  22. #include <pwd.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27.  
  28. #include "../common/common.h"
  29.  
  30. /*
  31.  * ex_cd -- :cd[!] [directory]
  32.  *    Change directories.
  33.  *
  34.  * PUBLIC: int ex_cd __P((SCR *, EXCMD *));
  35.  */
  36. int
  37. ex_cd(sp, cmdp)
  38.     SCR *sp;
  39.     EXCMD *cmdp;
  40. {
  41.     struct passwd *pw;
  42.     ARGS *ap;
  43.     CHAR_T savech;
  44.     char *dir, *p, *t;    /* XXX: END OF THE STACK, DON'T TRUST GETCWD. */
  45.     char buf[MAXPATHLEN * 2];
  46.  
  47.     /*
  48.      * !!!
  49.      * Historic practice is that the cd isn't attempted if the file has
  50.      * been modified, unless its name begins with a leading '/' or the
  51.      * force flag is set.
  52.      */
  53. #if VI_DOSISH
  54.     /*
  55.      * ...which is an absolute B*TCH when a rooted path has either a drive
  56.      * letter or UNC, and you can use either / or \ as path separator....
  57.      * (Late note:  emx beat me to it!)
  58.      */
  59.     if (F_ISSET(sp->ep, F_MODIFIED) &&
  60.         !FL_ISSET(cmdp->iflags, E_C_FORCE) &&
  61.         !_fnisabs(sp->frp->name)) {
  62. #else
  63.     if (F_ISSET(sp->ep, F_MODIFIED) &&
  64.         !FL_ISSET(cmdp->iflags, E_C_FORCE) && sp->frp->name[0] != '/') {
  65. #endif
  66.         msgq(sp, M_ERR,
  67.     "120|File modified since last complete write; write or use ! to override");
  68.         return (1);
  69.     }
  70.  
  71.     switch (cmdp->argc) {
  72.     case 0:
  73.         /* If no argument, change to the user's home directory. */
  74.         if ((dir = getenv("HOME")) == NULL) {
  75.             if ((pw = getpwuid(getuid())) == NULL ||
  76.                 pw->pw_dir == NULL || pw->pw_dir[0] == '\0') {
  77.                 msgq(sp, M_ERR,
  78.                "121|Unable to find home directory location");
  79.                 return (1);
  80.             }
  81.             dir = pw->pw_dir;
  82.         }
  83.         break;
  84.     case 1:
  85.         dir = cmdp->argv[0]->bp;
  86.         break;
  87.     default:
  88.         abort();
  89.     }
  90.  
  91.     /*
  92.      * Try the current directory first.  If this succeeds, don't display
  93.      * a message, vi didn't historically, and it should be obvious to the
  94.      * user where they are.
  95.      */
  96. #ifdef __EMX__
  97.     if (!_chdir2(dir))
  98. #else
  99.     if (!chdir(dir))
  100. #endif
  101.         return (0);
  102.  
  103.     /*
  104.      * If moving to the user's home directory, or, the path begins with
  105.      * "/", "./" or "../", it's the only place we try.
  106.      */
  107.     if (cmdp->argc == 0 ||
  108.         (ap = cmdp->argv[0])->bp[0] == '/' ||
  109.         ap->len == 1 && ap->bp[0] == '.' ||
  110.         ap->len >= 2 && ap->bp[0] == '.' && ap->bp[1] == '.' &&
  111.         (ap->bp[2] == '/' || ap->bp[2] == '\0'))
  112.         goto err;
  113.  
  114.     /* Try the O_CDPATH option values. */
  115.     for (p = t = O_STR(sp, O_CDPATH);; ++p)
  116. #if VI_DOSISH
  117.         if (*p == '\0' || *p == ';') {
  118. #else
  119.         if (*p == '\0' || *p == ':') {
  120. #endif
  121.             /*
  122.              * Empty strings specify ".".  The only way to get an
  123.              * empty string is a leading colon, colons in a row,
  124.              * or a trailing colon.  Or, to put it the other way,
  125.              * if the length is 1 or less, then we're dealing with
  126.              * ":XXX", "XXX::XXXX" , "XXX:", or "".  Since we've
  127.              * already tried dot, we ignore tham all.
  128.              */
  129.             if (t < p - 1) {
  130.                 savech = *p;
  131.                 *p = '\0';
  132.                 (void)snprintf(buf,
  133.                     sizeof(buf), "%s/%s", t, dir);
  134.                 *p = savech;
  135. #ifdef __EMX__
  136.                 if (!_chdir2(buf)) {
  137.                     if (_getcwd2(buf, sizeof(buf)) != NULL)
  138. #else
  139.                 if (!chdir(buf)) {
  140.                     if (getcwd(buf, sizeof(buf)) != NULL)
  141. #endif
  142.         msgq_str(sp, M_INFO, buf, "122|New current directory: %s");
  143.                     return (0);
  144.                 }
  145.             }
  146.             t = p + 1;
  147.             if (*p == '\0')
  148.                 break;
  149.         }
  150.  
  151. err:    msgq_str(sp, M_SYSERR, dir, "%s");
  152.     return (1);
  153. }
  154.