📄 pushd.def
字号:
This file is pushd.def, from which is created pushd.c. It implements thebuiltins "pushd", "popd", and "dirs" in Bash.Copyright (C) 1987-2009 Free Software Foundation, Inc.This file is part of GNU Bash, the Bourne Again SHell.Bash is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.Bash is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with Bash. If not, see <http://www.gnu.org/licenses/>.$PRODUCES pushd.c$BUILTIN pushd$FUNCTION pushd_builtin$DEPENDS_ON PUSHD_AND_POPD$SHORT_DOC pushd [-n] [+N | -N | dir]Add directories to stack.Adds a directory to the top of the directory stack, or rotatesthe stack, making the new top of the stack the current workingdirectory. With no arguments, exchanges the top two directories.Options: -n Suppresses the normal change of directory when adding directories to the stack, so only the stack is manipulated.Arguments: +N Rotates the stack so that the Nth directory (counting from the left of the list shown by `dirs', starting with zero) is at the top. -N Rotates the stack so that the Nth directory (counting from the right of the list shown by `dirs', starting with zero) is at the top. dir Adds DIR to the directory stack at the top, making it the new current working directory.The `dirs' builtin displays the directory stack.Exit Status:Returns success unless an invalid argument is supplied or the directorychange fails.$END$BUILTIN popd$FUNCTION popd_builtin$DEPENDS_ON PUSHD_AND_POPD$SHORT_DOC popd [-n] [+N | -N]Remove directories from stack.Removes entries from the directory stack. With no arguments, removesthe top directory from the stack, and changes to the new top directory.Options: -n Suppresses the normal change of directory when removing directories from the stack, so only the stack is manipulated.Arguments: +N Removes the Nth entry counting from the left of the list shown by `dirs', starting with zero. For example: `popd +0' removes the first directory, `popd +1' the second. -N Removes the Nth entry counting from the right of the list shown by `dirs', starting with zero. For example: `popd -0' removes the last directory, `popd -1' the next to last.The `dirs' builtin displays the directory stack.Exit Status:Returns success unless an invalid argument is supplied or the directorychange fails.$END$BUILTIN dirs$FUNCTION dirs_builtin$DEPENDS_ON PUSHD_AND_POPD$SHORT_DOC dirs [-clpv] [+N] [-N]Display directory stack.Display the list of currently remembered directories. Directoriesfind their way onto the list with the `pushd' command; you can getback up through the list with the `popd' command.Options: -c clear the directory stack by deleting all of the elements -l do not print tilde-prefixed versions of directories relative to your home directory -p print the directory stack with one entry per line -v print the directory stack with one entry per line prefixed with its position in the stackArguments: +N Displays the Nth entry counting from the left of the list shown by dirs when invoked without options, starting with zero. -N Displays the Nth entry counting from the right of the list shown by dirs when invoked without options, starting with zero.Exit Status:Returns success unless an invalid option is supplied or an error occurs.$END#include <config.h>#if defined (PUSHD_AND_POPD)#include <stdio.h>#ifndef _MINIX# include <sys/param.h>#endif#if defined (HAVE_UNISTD_H)# ifdef _MINIX# include <sys/types.h># endif# include <unistd.h>#endif#include "../bashansi.h"#include "../bashintl.h"#include <errno.h>#include <tilde/tilde.h>#include "../shell.h"#include "maxpath.h"#include "common.h"#include "builtext.h"#ifdef LOADABLE_BUILTIN# include "builtins.h"#endif#if !defined (errno)extern int errno;#endif /* !errno *//* The list of remembered directories. */static char **pushd_directory_list = (char **)NULL;/* Number of existing slots in this list. */static int directory_list_size;/* Offset to the end of the list. */static int directory_list_offset;static void pushd_error __P((int, char *));static void clear_directory_stack __P((void));static int cd_to_string __P((char *));static int change_to_temp __P((char *));static void add_dirstack_element __P((char *));static int get_dirstack_index __P((intmax_t, int, int *));#define NOCD 0x01#define ROTATE 0x02#define LONGFORM 0x04#define CLEARSTAK 0x08intpushd_builtin (list) WORD_LIST *list;{ WORD_LIST *orig_list; char *temp, *current_directory, *top; int j, flags, skipopt; intmax_t num; char direction; orig_list = list; if (list && list->word && ISOPTION (list->word->word, '-')) { list = list->next; skipopt = 1; } else skipopt = 0; /* If there is no argument list then switch current and top of list. */ if (list == 0) { if (directory_list_offset == 0) { builtin_error (_("no other directory")); return (EXECUTION_FAILURE); } current_directory = get_working_directory ("pushd"); if (current_directory == 0) return (EXECUTION_FAILURE); j = directory_list_offset - 1; temp = pushd_directory_list[j]; pushd_directory_list[j] = current_directory; j = change_to_temp (temp); free (temp); return j; } for (flags = 0; skipopt == 0 && list; list = list->next) { if (ISOPTION (list->word->word, 'n')) { flags |= NOCD; } else if (ISOPTION (list->word->word, '-')) { list = list->next; break; } else if (list->word->word[0] == '-' && list->word->word[1] == '\0') /* Let `pushd -' work like it used to. */ break; else if (((direction = list->word->word[0]) == '+') || direction == '-') { if (legal_number (list->word->word + 1, &num) == 0) { sh_invalidnum (list->word->word); builtin_usage (); return (EXECUTION_FAILURE); } if (direction == '-') num = directory_list_offset - num; if (num > directory_list_offset || num < 0) { pushd_error (directory_list_offset, list->word->word); return (EXECUTION_FAILURE); } flags |= ROTATE; } else if (*list->word->word == '-') { sh_invalidopt (list->word->word); builtin_usage (); return (EXECUTION_FAILURE); } else break; } if (flags & ROTATE) { /* Rotate the stack num times. Remember, the current directory acts like it is part of the stack. */ temp = get_working_directory ("pushd"); if (num == 0) { j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS; free (temp); return j; } do { top = pushd_directory_list[directory_list_offset - 1]; for (j = directory_list_offset - 2; j > -1; j--) pushd_directory_list[j + 1] = pushd_directory_list[j]; pushd_directory_list[j + 1] = temp; temp = top; num--; } while (num); j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS; free (temp); return j; } if (list == 0) return (EXECUTION_SUCCESS); /* Change to the directory in list->word->word. Save the current directory on the top of the stack. */ current_directory = get_working_directory ("pushd"); if (current_directory == 0) return (EXECUTION_FAILURE); j = ((flags & NOCD) == 0) ? cd_builtin (skipopt ? orig_list : list) : EXECUTION_SUCCESS; if (j == EXECUTION_SUCCESS) { add_dirstack_element ((flags & NOCD) ? savestring (list->word->word) : current_directory); dirs_builtin ((WORD_LIST *)NULL); if (flags & NOCD) free (current_directory); return (EXECUTION_SUCCESS); } else { free (current_directory); return (EXECUTION_FAILURE); }}/* Pop the directory stack, and then change to the new top of the stack. If LIST is non-null it should consist of a word +N or -N, which says what element to delete from the stack. The default is the top one. */intpopd_builtin (list) WORD_LIST *list;{ register int i; intmax_t which; int flags; char direction; char *which_word; which_word = (char *)NULL; for (flags = 0, which = 0, direction = '+'; list; list = list->next) { if (ISOPTION (list->word->word, 'n')) { flags |= NOCD; } else if (ISOPTION (list->word->word, '-')) { list = list->next; break; } else if (((direction = list->word->word[0]) == '+') || direction == '-') { if (legal_number (list->word->word + 1, &which) == 0) { sh_invalidnum (list->word->word); builtin_usage (); return (EXECUTION_FAILURE); } which_word = list->word->word; } else if (*list->word->word == '-') { sh_invalidopt (list->word->word); builtin_usage (); return (EXECUTION_FAILURE); } else break; } if (which > directory_list_offset || (directory_list_offset == 0 && which == 0)) { pushd_error (directory_list_offset, which_word ? which_word : ""); return (EXECUTION_FAILURE); } /* Handle case of no specification, or top of stack specification. */ if ((direction == '+' && which == 0) || (direction == '-' && which == directory_list_offset)) { i = ((flags & NOCD) == 0) ? cd_to_string (pushd_directory_list[directory_list_offset - 1]) : EXECUTION_SUCCESS; if (i != EXECUTION_SUCCESS) return (i); free (pushd_directory_list[--directory_list_offset]); } else { /* Since an offset other than the top directory was specified, remove that directory from the list and shift the remainder of the list into place. */ i = (direction == '+') ? directory_list_offset - which : which; free (pushd_directory_list[i]); directory_list_offset--; /* Shift the remainder of the list into place. */ for (; i < directory_list_offset; i++) pushd_directory_list[i] = pushd_directory_list[i + 1]; } dirs_builtin ((WORD_LIST *)NULL); return (EXECUTION_SUCCESS);}/* Print the current list of directories on the directory stack. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -