Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / builtins / cd.def
1 This file is cd.def, from which is created cd.c.  It implements the
2 builtins "cd" and "pwd" in Bash.
3
4 Copyright (C) 1987-2013 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash.  If not, see <http://www.gnu.org/licenses/>.
20
21 $PRODUCES cd.c
22 #include <config.h>
23
24 #if defined (HAVE_UNISTD_H)
25 #  ifdef _MINIX
26 #    include <sys/types.h>
27 #  endif
28 #  include <unistd.h>
29 #endif
30
31 #include "../bashtypes.h"
32 #include "posixdir.h"
33 #include "posixstat.h"
34 #if defined (HAVE_SYS_PARAM_H)
35 #include <sys/param.h>
36 #endif
37 #include <fcntl.h>
38
39 #include <stdio.h>
40
41 #include "../bashansi.h"
42 #include "../bashintl.h"
43
44 #include <errno.h>
45 #include <tilde/tilde.h>
46
47 #include "../shell.h"
48 #include "../flags.h"
49 #include "maxpath.h"
50 #include "common.h"
51 #include "bashgetopt.h"
52
53 #if !defined (errno)
54 extern int errno;
55 #endif /* !errno */
56
57 extern int posixly_correct;
58 extern int array_needs_making;
59 extern const char * const bash_getcwd_errstr;
60
61 static int bindpwd __P((int));
62 static int setpwd __P((char *));
63 static char *resetpwd __P((char *));
64 static int change_to_directory __P((char *, int, int));
65
66 static int cdxattr __P((char *, char **));
67 static void resetxattr __P((void));
68
69 /* Change this to 1 to get cd spelling correction by default. */
70 int cdspelling = 0;
71
72 int cdable_vars;
73
74 static int eflag;       /* file scope so bindpwd() can see it */
75 static int xattrflag;   /* O_XATTR support for openat */
76 static int xattrfd = -1;
77
78 $BUILTIN cd
79 $FUNCTION cd_builtin
80 $SHORT_DOC cd [-L|[-P [-e]] [-@]] [dir]
81 Change the shell working directory.
82
83 Change the current directory to DIR.  The default DIR is the value of the
84 HOME shell variable.
85
86 The variable CDPATH defines the search path for the directory containing
87 DIR.  Alternative directory names in CDPATH are separated by a colon (:).
88 A null directory name is the same as the current directory.  If DIR begins
89 with a slash (/), then CDPATH is not used.
90
91 If the directory is not found, and the shell option `cdable_vars' is set,
92 the word is assumed to be  a variable name.  If that variable has a value,
93 its value is used for DIR.
94
95 Options:
96     -L  force symbolic links to be followed: resolve symbolic links in
97         DIR after processing instances of `..'
98     -P  use the physical directory structure without following symbolic
99         links: resolve symbolic links in DIR before processing instances
100         of `..'
101     -e  if the -P option is supplied, and the current working directory
102         cannot be determined successfully, exit with a non-zero status
103 #if defined (O_XATTR)
104     -@  on systems that support it, present a file with extended attributes
105         as a directory containing the file attributes
106 #endif
107
108 The default is to follow symbolic links, as if `-L' were specified.
109 `..' is processed by removing the immediately previous pathname component
110 back to a slash or the beginning of DIR.
111
112 Exit Status:
113 Returns 0 if the directory is changed, and if $PWD is set successfully when
114 -P is used; non-zero otherwise.
115 $END
116
117 /* Just set $PWD, don't change OLDPWD.  Used by `pwd -P' in posix mode. */
118 static int
119 setpwd (dirname)
120      char *dirname;
121 {
122   int old_anm;
123   SHELL_VAR *tvar;
124
125   old_anm = array_needs_making;
126   tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
127   if (tvar && readonly_p (tvar))
128     return EXECUTION_FAILURE;
129   if (tvar && old_anm == 0 && array_needs_making && exported_p (tvar))
130     {
131       update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
132       array_needs_making = 0;
133     }
134   return EXECUTION_SUCCESS;
135 }
136
137 static int
138 bindpwd (no_symlinks)
139      int no_symlinks;
140 {
141   char *dirname, *pwdvar;
142   int old_anm, r;
143   SHELL_VAR *tvar;
144
145   r = sh_chkwrite (EXECUTION_SUCCESS);
146
147 #define tcwd the_current_working_directory
148   dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
149                  : get_working_directory ("cd");
150 #undef tcwd
151
152   old_anm = array_needs_making;
153   pwdvar = get_string_value ("PWD");
154
155   tvar = bind_variable ("OLDPWD", pwdvar, 0);
156   if (tvar && readonly_p (tvar))
157     r = EXECUTION_FAILURE;
158
159   if (old_anm == 0 && array_needs_making && exported_p (tvar))
160     {
161       update_export_env_inplace ("OLDPWD=", 7, pwdvar);
162       array_needs_making = 0;
163     }
164
165   if (setpwd (dirname) == EXECUTION_FAILURE)
166     r = EXECUTION_FAILURE;
167   if (dirname == 0 && eflag)
168     r = EXECUTION_FAILURE;
169
170   if (dirname && dirname != the_current_working_directory)
171     free (dirname);
172
173   return (r);
174 }
175
176 /* Call get_working_directory to reset the value of
177    the_current_working_directory () */
178 static char *
179 resetpwd (caller)
180      char *caller;
181 {
182   char *tdir;
183       
184   FREE (the_current_working_directory);
185   the_current_working_directory = (char *)NULL;
186   tdir = get_working_directory (caller);
187   return (tdir);
188 }
189
190 static int
191 cdxattr (dir, ndirp)
192      char *dir;         /* don't assume we can always free DIR */
193      char **ndirp;      /* return new constructed directory name */
194 {
195 #if defined (O_XATTR)
196   int apfd, fd, r, e;
197   char buf[11+40+40];   /* construct new `fake' path for pwd */
198
199   apfd = openat (AT_FDCWD, dir, O_RDONLY|O_NONBLOCK);
200   if (apfd < 0)
201     return -1;
202   fd = openat (apfd, ".", O_XATTR);
203   e = errno;
204   close (apfd);         /* ignore close error for now */
205   errno = e;
206   if (fd < 0)
207     return -1;
208   r = fchdir (fd);      /* assume fchdir exists everywhere with O_XATTR */
209   if (r < 0)
210     {
211       close (fd);
212       return -1;
213     }
214   /* NFSv4 and ZFS extended attribute directories do not have names which are
215      visible in the standard Unix directory tree structure.  To ensure we have
216      a valid name for $PWD, we synthesize one under /proc, but to keep that
217      path valid, we need to keep the file descriptor open as long as we are in
218      this directory.  This imposes a certain structure on /proc. */
219   if (ndirp)
220     {
221       sprintf (buf, "/proc/%d/fd/%d", getpid(), fd);
222       *ndirp = savestring (buf);
223     }
224
225   if (xattrfd >= 0)
226     close (xattrfd);
227   xattrfd = fd;  
228
229   return r;
230 #else
231   return -1;
232 #endif
233 }
234
235 /* Clean up the O_XATTR baggage.  Currently only closes xattrfd */
236 static void
237 resetxattr ()
238 {
239 #if defined (O_XATTR)
240   if (xattrfd >= 0)
241     {
242       close (xattrfd);
243       xattrfd = -1;
244     }
245 #else
246   xattrfd = -1;         /* not strictly necessary */
247 #endif
248 }
249
250 #define LCD_DOVARS      0x001
251 #define LCD_DOSPELL     0x002
252 #define LCD_PRINTPATH   0x004
253 #define LCD_FREEDIRNAME 0x008
254
255 /* This builtin is ultimately the way that all user-visible commands should
256    change the current working directory.  It is called by cd_to_string (),
257    so the programming interface is simple, and it handles errors and
258    restrictions properly. */
259 int
260 cd_builtin (list)
261      WORD_LIST *list;
262 {
263   char *dirname, *cdpath, *path, *temp;
264   int path_index, no_symlinks, opt, lflag;
265
266 #if defined (RESTRICTED_SHELL)
267   if (restricted)
268     {
269       sh_restricted ((char *)NULL);
270       return (EXECUTION_FAILURE);
271     }
272 #endif /* RESTRICTED_SHELL */
273
274   eflag = 0;
275   no_symlinks = no_symbolic_links;
276   xattrflag = 0;
277   reset_internal_getopt ();
278 #if defined (O_XATTR)
279   while ((opt = internal_getopt (list, "eLP@")) != -1)
280 #else
281   while ((opt = internal_getopt (list, "eLP")) != -1)
282 #endif
283     {
284       switch (opt)
285         {
286         case 'P':
287           no_symlinks = 1;
288           break;
289         case 'L':
290           no_symlinks = 0;
291           break;
292         case 'e':
293           eflag = 1;
294           break;
295 #if defined (O_XATTR)
296         case '@':
297           xattrflag = 1;
298           break;
299 #endif
300         default:
301           builtin_usage ();
302           return (EX_USAGE);
303         }
304     }
305   list = loptend;
306
307   lflag = (cdable_vars ? LCD_DOVARS : 0) |
308           ((interactive && cdspelling) ? LCD_DOSPELL : 0);
309   if (eflag && no_symlinks == 0)
310     eflag = 0;
311
312   if (list == 0)
313     {
314       /* `cd' without arguments is equivalent to `cd $HOME' */
315       dirname = get_string_value ("HOME");
316
317       if (dirname == 0)
318         {
319           builtin_error (_("HOME not set"));
320           return (EXECUTION_FAILURE);
321         }
322       lflag = 0;
323     }
324 #if defined (CD_COMPLAINS)
325   else if (list->next)
326     {
327       builtin_error (_("too many arguments"));
328       return (EXECUTION_FAILURE);
329     }
330 #endif
331   else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
332     {
333       /* This is `cd -', equivalent to `cd $OLDPWD' */
334       dirname = get_string_value ("OLDPWD");
335
336       if (dirname == 0)
337         {
338           builtin_error (_("OLDPWD not set"));
339           return (EXECUTION_FAILURE);
340         }
341 #if 0
342       lflag = interactive ? LCD_PRINTPATH : 0;
343 #else
344       lflag = LCD_PRINTPATH;            /* According to SUSv3 */
345 #endif
346     }
347   else if (absolute_pathname (list->word->word))
348     dirname = list->word->word;
349   else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
350     {
351       dirname = list->word->word;
352
353       /* Find directory in $CDPATH. */
354       path_index = 0;
355       while (path = extract_colon_unit (cdpath, &path_index))
356         {
357           /* OPT is 1 if the path element is non-empty */
358           opt = path[0] != '\0';
359           temp = sh_makepath (path, dirname, MP_DOTILDE);
360           free (path);
361
362           if (change_to_directory (temp, no_symlinks, xattrflag))
363             {
364               /* POSIX.2 says that if a nonempty directory from CDPATH
365                  is used to find the directory to change to, the new
366                  directory name is echoed to stdout, whether or not
367                  the shell is interactive. */
368               if (opt && (path = no_symlinks ? temp : the_current_working_directory))
369                 printf ("%s\n", path);
370
371               free (temp);
372 #if 0
373               /* Posix.2 says that after using CDPATH, the resultant
374                  value of $PWD will not contain `.' or `..'. */
375               return (bindpwd (posixly_correct || no_symlinks));
376 #else
377               return (bindpwd (no_symlinks));
378 #endif
379             }
380           else
381             free (temp);
382         }
383
384 #if 0
385       /* changed for bash-4.2 Posix cd description steps 5-6 */
386       /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
387          try the current directory, so we just punt now with an error
388          message if POSIXLY_CORRECT is non-zero.  The check for cdpath[0]
389          is so we don't mistakenly treat a CDPATH value of "" as not
390          specifying the current directory. */
391       if (posixly_correct && cdpath[0])
392         {
393           builtin_error ("%s: %s", dirname, strerror (ENOENT));
394           return (EXECUTION_FAILURE);
395         }
396 #endif
397     }
398   else
399     dirname = list->word->word;
400
401   /* When we get here, DIRNAME is the directory to change to.  If we
402      chdir successfully, just return. */
403   if (change_to_directory (dirname, no_symlinks, xattrflag))
404     {
405       if (lflag & LCD_PRINTPATH)
406         printf ("%s\n", dirname);
407       return (bindpwd (no_symlinks));
408     }
409
410   /* If the user requests it, then perhaps this is the name of
411      a shell variable, whose value contains the directory to
412      change to. */
413   if (lflag & LCD_DOVARS)
414     {
415       temp = get_string_value (dirname);
416       if (temp && change_to_directory (temp, no_symlinks, xattrflag))
417         {
418           printf ("%s\n", temp);
419           return (bindpwd (no_symlinks));
420         }
421     }
422
423   /* If the user requests it, try to find a directory name similar in
424      spelling to the one requested, in case the user made a simple
425      typo.  This is similar to the UNIX 8th and 9th Edition shells. */
426   if (lflag & LCD_DOSPELL)
427     {
428       temp = dirspell (dirname);
429       if (temp && change_to_directory (temp, no_symlinks, xattrflag))
430         {
431           printf ("%s\n", temp);
432           free (temp);
433           return (bindpwd (no_symlinks));
434         }
435       else
436         FREE (temp);
437     }
438
439   builtin_error ("%s: %s", dirname, strerror (errno));
440   return (EXECUTION_FAILURE);
441 }
442
443 $BUILTIN pwd
444 $FUNCTION pwd_builtin
445 $SHORT_DOC pwd [-LP]
446 Print the name of the current working directory.
447
448 Options:
449   -L    print the value of $PWD if it names the current working
450         directory
451   -P    print the physical directory, without any symbolic links
452
453 By default, `pwd' behaves as if `-L' were specified.
454
455 Exit Status:
456 Returns 0 unless an invalid option is given or the current directory
457 cannot be read.
458 $END
459
460 /* Non-zero means that pwd always prints the physical directory, without
461    symbolic links. */
462 static int verbatim_pwd;
463
464 /* Print the name of the current working directory. */
465 int
466 pwd_builtin (list)
467      WORD_LIST *list;
468 {
469   char *directory;
470   int opt, pflag;
471
472   verbatim_pwd = no_symbolic_links;
473   pflag = 0;
474   reset_internal_getopt ();
475   while ((opt = internal_getopt (list, "LP")) != -1)
476     {
477       switch (opt)
478         {
479         case 'P':
480           verbatim_pwd = pflag = 1;
481           break;
482         case 'L':
483           verbatim_pwd = 0;
484           break;
485         default:
486           builtin_usage ();
487           return (EX_USAGE);
488         }
489     }
490   list = loptend;
491
492 #define tcwd the_current_working_directory
493
494   directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
495                    : get_working_directory ("pwd");
496
497   /* Try again using getcwd() if canonicalization fails (for instance, if
498      the file system has changed state underneath bash). */
499   if ((tcwd && directory == 0) ||
500       (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
501     {
502       if (directory && directory != tcwd)
503         free (directory);
504       directory = resetpwd ("pwd");
505     }
506
507 #undef tcwd
508
509   if (directory)
510     {
511       opt = EXECUTION_SUCCESS;
512       printf ("%s\n", directory);
513       /* This is dumb but posix-mandated. */
514       if (posixly_correct && pflag)
515         opt = setpwd (directory);
516       if (directory != the_current_working_directory)
517         free (directory);
518       return (sh_chkwrite (opt));
519     }
520   else
521     return (EXECUTION_FAILURE);
522 }
523
524 /* Do the work of changing to the directory NEWDIR.  Handle symbolic
525    link following, etc.  This function *must* return with
526    the_current_working_directory either set to NULL (in which case
527    getcwd() will eventually be called), or set to a string corresponding
528    to the working directory.  Return 1 on success, 0 on failure. */
529
530 static int
531 change_to_directory (newdir, nolinks, xattr)
532      char *newdir;
533      int nolinks, xattr;
534 {
535   char *t, *tdir, *ndir;
536   int err, canon_failed, r, ndlen, dlen;
537
538   tdir = (char *)NULL;
539
540   if (the_current_working_directory == 0)
541     {
542       t = get_working_directory ("chdir");
543       FREE (t);
544     }
545
546   t = make_absolute (newdir, the_current_working_directory);
547
548   /* TDIR is either the canonicalized absolute pathname of NEWDIR
549      (nolinks == 0) or the absolute physical pathname of NEWDIR
550      (nolinks != 0). */
551   tdir = nolinks ? sh_physpath (t, 0)
552                  : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
553
554   ndlen = strlen (newdir);
555   dlen = strlen (t);
556
557   /* Use the canonicalized version of NEWDIR, or, if canonicalization
558      failed, use the non-canonical form. */
559   canon_failed = 0;
560   if (tdir && *tdir)
561     free (t);
562   else
563     {
564       FREE (tdir);
565       tdir = t;
566       canon_failed = 1;
567     }
568
569   /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
570      returns NULL (because it checks the path, it will return NULL if the
571      resolved path doesn't exist), fail immediately. */
572   if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
573     {
574 #if defined ENAMETOOLONG
575       if (errno != ENOENT && errno != ENAMETOOLONG)
576 #else
577       if (errno != ENOENT)
578 #endif
579         errno = ENOTDIR;
580       free (tdir);
581       return (0);
582     }
583
584 #if defined (O_XATTR)
585   if (xattrflag)
586     {
587       r = cdxattr (nolinks ? newdir : tdir, &ndir);
588       if (r >= 0)
589         {
590           canon_failed = 0;
591           free (tdir);
592           tdir = ndir;
593         }
594       else
595         {
596           err = errno;
597           free (tdir);
598           errno = err;
599           return (0);           /* no xattr */
600         }
601     }
602   else
603 #endif
604     {
605       r = chdir (nolinks ? newdir : tdir);
606       if (r >= 0)
607         resetxattr ();
608     }
609
610   /* If the chdir succeeds, update the_current_working_directory. */
611   if (r == 0)
612     {
613       /* If canonicalization failed, but the chdir succeeded, reset the
614          shell's idea of the_current_working_directory. */
615       if (canon_failed)
616         {
617           t = resetpwd ("cd");
618           if (t == 0)
619             set_working_directory (tdir);
620           else
621             free (t);
622         }
623       else
624         set_working_directory (tdir);
625
626       free (tdir);
627       return (1);
628     }
629
630   /* We failed to change to the appropriate directory name.  If we tried
631      what the user passed (nolinks != 0), punt now. */
632   if (nolinks)
633     {
634       free (tdir);
635       return (0);
636     }
637
638   err = errno;
639
640   /* We're not in physical mode (nolinks == 0), but we failed to change to
641      the canonicalized directory name (TDIR).  Try what the user passed
642      verbatim. If we succeed, reinitialize the_current_working_directory. */
643   if (chdir (newdir) == 0)
644     {
645       t = resetpwd ("cd");
646       if (t == 0)
647         set_working_directory (tdir);
648       else
649         free (t);
650
651       r = 1;
652     }
653   else
654     {
655       errno = err;
656       r = 0;
657     }
658
659   free (tdir);
660   return r;
661 }