Logo Search packages:      
Sourcecode: ksh version File versions  Download package

cd_pwd.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*                  Copyright (c) 1982-2005 AT&T Corp.                  *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                            by AT&T Corp.                             *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                  David Korn <dgk@research.att.com>                   *
*                                                                      *
***********************************************************************/
#pragma prototyped
/*
 * cd [-LP]  [dirname]
 * cd [-LP]  [old] [new]
 * pwd [-LP]
 *
 *   David Korn
 *   AT&T Labs
 *   research!dgk
 *
 */

#include    "defs.h"
#include    <stak.h>
#include    <error.h>
#include    "variables.h"
#include    "path.h"
#include    "name.h"
#include    "builtins.h"
#include    <ls.h>
#include    <ctype.h>

#ifdef PATH_BFPATH
/*
 * Invalidate path name bindings to relative paths
 */
static void rehash(register Namval_t *np,void *data)
{
      Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
      NOT_USED(data);
      if(pp && *pp->name!='/')
            nv_unset(np);
}
#endif

int   b_cd(int argc, char *argv[],void *extra)
{
#ifdef PATH_BFPATH
      register char *dir;
      Pathcomp_t *cdpath = 0;
#else
      register char *dir, *cdpath="";
#endif
      register const char *dp;
      register Shell_t *shp = (Shell_t*)extra;
      int saverrno=0;
      int rval,flag=0;
      char *oldpwd;
      Namval_t *opwdnod, *pwdnod;
      if(sh_isoption(SH_RESTRICTED))
            errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
      while((rval = optget(argv,sh_optcd))) switch(rval)
      {
            case 'L':
                  flag = 0;
                  break;
            case 'P':
                  flag = 1;
                  break;
            case ':':
                  errormsg(SH_DICT,2, "%s", opt_info.arg);
                  break;
            case '?':
                  errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
                  break;
      }
      argv += opt_info.index;
      argc -= opt_info.index;
      dir =  argv[0];
      if(error_info.errors>0 || argc >2)
            errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
      oldpwd = (char*)shp->pwd;
      opwdnod = (shp->subshell?sh_assignok(OLDPWDNOD,1):OLDPWDNOD); 
      pwdnod = (shp->subshell?sh_assignok(PWDNOD,1):PWDNOD); 
      if(argc==2)
            dir = sh_substitute(oldpwd,dir,argv[1]);
      else if(!dir || *dir==0)
            dir = nv_getval(HOME);
      else if(*dir == '-' && dir[1]==0)
            dir = nv_getval(opwdnod);
      if(!dir || *dir==0)
            errormsg(SH_DICT,ERROR_exit(1),argc==2?e_subst+4:e_direct);
#if _WINIX
      if(*dir != '/' && (dir[1]!=':'))
#else
#endif /* _WINIX */
      if(*dir != '/')
      {
#ifdef PATH_BFPATH
            if(!(cdpath = (Pathcomp_t*)shp->cdpathlist) && (dp=(CDPNOD)->nvalue.cp))
            {
                  if(cdpath=path_addpath((Pathcomp_t*)0,dp,PATH_CDPATH))
                  {
                        shp->cdpathlist = (void*)cdpath;
                        cdpath->shp = shp;
                  }
            }
#else
            cdpath = nv_getval(nv_scoped(CDPNOD));
#endif
            if(!oldpwd)
                  oldpwd = path_pwd(1);
      }
#ifndef PATH_BFPATH
      if(!cdpath)
            cdpath = "";
#endif
      if(*dir=='.')
      {
            /* test for pathname . ./ .. or ../ */
            if(*(dp=dir+1) == '.')
                  dp++;
            if(*dp==0 || *dp=='/')
#ifdef PATH_BFPATH
                  cdpath = 0;
#else
                  cdpath = "";
#endif
      }
      rval = -1;
      do
      {
#ifdef PATH_BFPATH
            dp = cdpath?cdpath->name:"";
            cdpath = path_nextcomp(cdpath,dir,0);
#else
            dp = cdpath;
            cdpath=path_join(cdpath,dir);
#endif
#if _WINIX
                if(*stakptr(PATH_OFFSET+1)==':' && isalpha(*stakptr(PATH_OFFSET)))
            {
                  *stakptr(PATH_OFFSET+1) = *stakptr(PATH_OFFSET);
                  *stakptr(PATH_OFFSET)='/';
            }
#endif /* _WINIX */
                if(*stakptr(PATH_OFFSET)!='/')

            {
                  char *last=(char*)stakfreeze(1);
                  stakseek(PATH_OFFSET);
                  stakputs(oldpwd);
                  /* don't add '/' of oldpwd is / itself */
                  if(*oldpwd!='/' || oldpwd[1])
                        stakputc('/');
                  stakputs(last+PATH_OFFSET);
                  stakputc(0);
            }
            if(!flag)
            {
                  register char *cp;
                  stakseek(PATH_MAX+PATH_OFFSET);
#if SHOPT_FS_3D
                  if(!(cp = pathcanon(stakptr(PATH_OFFSET),PATH_DOTDOT)))
                        continue;
                  /* eliminate trailing '/' */
                  while(*--cp == '/' && cp>stakptr(PATH_OFFSET))
                        *cp = 0;
#else
                  if(*(cp=stakptr(PATH_OFFSET))=='/')
                        if(!pathcanon(cp,PATH_DOTDOT))
                              continue;
#endif /* SHOPT_FS_3D */
            }
            if((rval=chdir(path_relative(stakptr(PATH_OFFSET)))) >= 0)
                  goto success;
            if(errno!=ENOENT && saverrno==0)
                  saverrno=errno;
      }
      while(cdpath);
      if(rval<0 && *dir=='/' && *(path_relative(stakptr(PATH_OFFSET)))!='/')
            rval = chdir(dir);
      /* use absolute chdir() if relative chdir() fails */
      if(rval<0)
      {
            if(saverrno)
                  errno = saverrno;
            errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
      }
success:
      if(dir == nv_getval(opwdnod) || argc==2)
            dp = dir;   /* print out directory for cd - */
      if(flag)
      {
            dir = stakptr(PATH_OFFSET);
            if (!(dir=pathcanon(dir,PATH_PHYSICAL)))
            {
                  dir = stakptr(PATH_OFFSET);
                  errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
            }
            stakseek(dir-stakptr(0));
      }
      dir = (char*)stakfreeze(1)+PATH_OFFSET;
#ifdef PATH_BFPATH
      if(*dp && (*dp!='.'||dp[1]) && strchr(dir,'/'))
#else
      if(*dp && *dp!= ':' && strchr(dir,'/'))
#endif
            sfputr(sfstdout,dir,'\n');
      if(*dir != '/')
            return(0);
      nv_putval(opwdnod,oldpwd,NV_RDONLY);
      if(oldpwd)
            free(oldpwd);
      flag = strlen(dir);
      /* delete trailing '/' */
      while(--flag>0 && dir[flag]=='/')
            dir[flag] = 0;
      nv_putval(pwdnod,dir,NV_RDONLY);
      nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
      shp->pwd = pwdnod->nvalue.cp;
#ifdef PATH_BFPATH
      nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
      path_newdir(shp->pathlist);
      path_newdir(shp->cdpathlist);
#endif
      return(0);
}

int   b_pwd(int argc, char *argv[],void *extra)
{
      register int n, flag = 0;
      register char *cp;
      register Shell_t *shp = (Shell_t*)extra;
      NOT_USED(argc);
      while((n = optget(argv,sh_optpwd))) switch(n)
      {
            case 'L':
                  flag = 0;
                  break;
            case 'P':
                  flag = 1;
                  break;
            case ':':
                  errormsg(SH_DICT,2, "%s", opt_info.arg);
                  break;
            case '?':
                  errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
                  break;
      }
      if(error_info.errors)
            errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
      if(*(cp = path_pwd(0)) != '/')
            errormsg(SH_DICT,ERROR_system(1), e_pwd);
      if(flag)
      {
#if SHOPT_FS_3D
            if(shp->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
            {
                  cp = (char*)stakseek(++flag+PATH_MAX);
                  mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0);
            }
            else
#endif /* SHOPT_FS_3D */
                  cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp);
            pathcanon(cp,PATH_PHYSICAL);
      }
      sfputr(sfstdout,cp,'\n');
      return(0);
}


Generated by  Doxygen 1.6.0   Back to index