/* * DIRSTACK.C - pushd / pop (directory stack) internal commands. * * * History: * * 14-Dec-1998 (Eric Kohl ) * Implemented PUSHD and POPD command. * * 20-Jan-1999 (Eric Kohl ) * Unicode and redirection safe! * * 20-Jan-1999 (Eric Kohl ) * Added DIRS command. */ #include "config.h" #ifdef FEATURE_DIRECTORY_STACK #include #include #include #include #include "cmd.h" typedef struct tagDIRENTRY { struct tagDIRENTRY *prev; struct tagDIRENTRY *next; LPTSTR pszPath; } DIRENTRY, *LPDIRENTRY; static INT nStackDepth; static LPDIRENTRY lpStackTop; static LPDIRENTRY lpStackBottom; static INT PushDirectory (LPTSTR pszPath) { LPDIRENTRY lpDir; lpDir = (LPDIRENTRY)malloc (sizeof (DIRENTRY)); if (!lpDir) { error_out_of_memory (); return -1; } lpDir->prev = NULL; if (lpStackTop == NULL) { lpDir->next = NULL; lpStackBottom = lpDir; } else { lpDir->next = lpStackTop; lpStackTop->prev = lpDir; } lpStackTop = lpDir; lpDir->pszPath = (LPTSTR)malloc ((_tcslen(pszPath)+1)*sizeof(TCHAR)); if (!lpDir->pszPath) { free (lpDir); error_out_of_memory (); return -1; } _tcscpy (lpDir->pszPath, pszPath); nStackDepth++; return 0; } static VOID PopDirectory (VOID) { LPDIRENTRY lpDir; if (nStackDepth == 0) return; lpDir = lpStackTop; lpStackTop = lpDir->next; if (lpStackTop != NULL) lpStackTop->prev = NULL; else lpStackBottom = NULL; free (lpDir->pszPath); free (lpDir); nStackDepth--; } static VOID GetDirectoryStackTop (LPTSTR pszPath) { if (lpStackTop) _tcsncpy (pszPath, lpStackTop->pszPath, MAX_PATH); else *pszPath = _T('\0'); } /* * initialize directory stack */ VOID InitDirectoryStack (VOID) { nStackDepth = 0; lpStackTop = NULL; lpStackBottom = NULL; } /* * destroy directory stack */ VOID DestroyDirectoryStack (VOID) { while (nStackDepth) PopDirectory (); } INT GetDirectoryStackDepth (VOID) { return nStackDepth; } /* * pushd command */ INT CommandPushd (LPTSTR first, LPTSTR rest) { TCHAR curPath[MAX_PATH]; TCHAR newPath[MAX_PATH]; BOOL bChangePath = FALSE; if (!_tcsncmp (rest, _T("/?"), 2)) { ConOutPuts (_T("Stores the current directory for use by the POPD command, then\n" "changes to the specified directory.\n\n" "PUSHD [path | ..]\n\n" " path Specifies the directory to make the current directory")); return 0; } if (rest[0] != _T('\0')) { GetFullPathName (rest, MAX_PATH, newPath, NULL); bChangePath = IsValidPathName (newPath); } GetCurrentDirectory (MAX_PATH, curPath); if (PushDirectory (curPath)) return 0; if (bChangePath) SetCurrentDirectory (newPath); return 0; } /* * popd command */ INT CommandPopd (LPTSTR first, LPTSTR rest) { TCHAR szPath[MAX_PATH]; if (!_tcsncmp(rest, _T("/?"), 2)) { ConOutPuts (_T("Changes to the directory stored by the PUSHD command.\n\n" "POPD")); return 0; } if (GetDirectoryStackDepth () == 0) return 0; GetDirectoryStackTop (szPath); PopDirectory (); SetCurrentDirectory (szPath); return 0; } /* * dirs command */ INT CommandDirs (LPTSTR first, LPTSTR rest) { LPDIRENTRY lpDir; if (!_tcsncmp(rest, _T("/?"), 2)) { ConOutPuts (_T("Prints the contents of the directory stack.\n" "\n" "DIRS")); return 0; } lpDir = lpStackBottom; if (lpDir == NULL) { ConOutPuts (_T("Directory stack empty")); return 0; } while (lpDir != NULL) { ConOutPuts (lpDir->pszPath); lpDir = lpDir->prev; } return 0; } #endif /* FEATURE_DIRECTORY_STACK */