xref: /reactos/base/shell/cmd/dirstack.c (revision 3f892a8d)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  *  DIRSTACK.C - pushd / pop (directory stack) internal commands.
3c2c66affSColin Finck  *
4c2c66affSColin Finck  *
5c2c66affSColin Finck  *  History:
6c2c66affSColin Finck  *
7c2c66affSColin Finck  *    14-Dec-1998 (Eric Kohl)
8c2c66affSColin Finck  *        Implemented PUSHD and POPD command.
9c2c66affSColin Finck  *
10c2c66affSColin Finck  *    20-Jan-1999 (Eric Kohl)
11c2c66affSColin Finck  *        Unicode and redirection safe!
12c2c66affSColin Finck  *
13c2c66affSColin Finck  *    20-Jan-1999 (Eric Kohl)
14c2c66affSColin Finck  *        Added DIRS command.
15c2c66affSColin Finck  */
16c2c66affSColin Finck 
17c2c66affSColin Finck #include "precomp.h"
18c2c66affSColin Finck 
19c2c66affSColin Finck #ifdef FEATURE_DIRECTORY_STACK
20c2c66affSColin Finck 
21c2c66affSColin Finck typedef struct tagDIRENTRY
22c2c66affSColin Finck {
23c2c66affSColin Finck     struct tagDIRENTRY *prev;
24c2c66affSColin Finck     struct tagDIRENTRY *next;
25c2c66affSColin Finck     TCHAR szPath[1];
26c2c66affSColin Finck } DIRENTRY, *LPDIRENTRY;
27c2c66affSColin Finck 
28c2c66affSColin Finck 
29c2c66affSColin Finck static INT nStackDepth;
30c2c66affSColin Finck static LPDIRENTRY lpStackTop;
31c2c66affSColin Finck static LPDIRENTRY lpStackBottom;
32c2c66affSColin Finck 
33c2c66affSColin Finck 
34c2c66affSColin Finck static INT
PushDirectory(LPTSTR pszPath)35c2c66affSColin Finck PushDirectory (LPTSTR pszPath)
36c2c66affSColin Finck {
37c2c66affSColin Finck     LPDIRENTRY lpDir = cmd_alloc(FIELD_OFFSET(DIRENTRY, szPath[_tcslen(pszPath) + 1]));
38c2c66affSColin Finck     if (!lpDir)
39c2c66affSColin Finck     {
40*3f892a8dSHermès Bélusca-Maïto         WARN("Cannot allocate memory for lpDir\n");
41c2c66affSColin Finck         error_out_of_memory();
42c2c66affSColin Finck         return -1;
43c2c66affSColin Finck     }
44c2c66affSColin Finck 
45c2c66affSColin Finck     lpDir->prev = NULL;
46c2c66affSColin Finck     lpDir->next = lpStackTop;
47c2c66affSColin Finck     if (lpStackTop == NULL)
48c2c66affSColin Finck         lpStackBottom = lpDir;
49c2c66affSColin Finck     else
50c2c66affSColin Finck         lpStackTop->prev = lpDir;
51c2c66affSColin Finck     lpStackTop = lpDir;
52c2c66affSColin Finck 
53c2c66affSColin Finck     _tcscpy(lpDir->szPath, pszPath);
54c2c66affSColin Finck 
55c2c66affSColin Finck     nStackDepth++;
56c2c66affSColin Finck 
57c2c66affSColin Finck     return nErrorLevel = 0;
58c2c66affSColin Finck }
59c2c66affSColin Finck 
60c2c66affSColin Finck 
61c2c66affSColin Finck static VOID
PopDirectory(VOID)62c2c66affSColin Finck PopDirectory (VOID)
63c2c66affSColin Finck {
64c2c66affSColin Finck     LPDIRENTRY lpDir = lpStackTop;
65c2c66affSColin Finck     lpStackTop = lpDir->next;
66c2c66affSColin Finck     if (lpStackTop != NULL)
67c2c66affSColin Finck         lpStackTop->prev = NULL;
68c2c66affSColin Finck     else
69c2c66affSColin Finck         lpStackBottom = NULL;
70c2c66affSColin Finck 
71c2c66affSColin Finck     cmd_free (lpDir);
72c2c66affSColin Finck 
73c2c66affSColin Finck     nStackDepth--;
74c2c66affSColin Finck }
75c2c66affSColin Finck 
76c2c66affSColin Finck 
77c2c66affSColin Finck /*
78c2c66affSColin Finck  * initialize directory stack
79c2c66affSColin Finck  */
InitDirectoryStack(VOID)80c2c66affSColin Finck VOID InitDirectoryStack (VOID)
81c2c66affSColin Finck {
82c2c66affSColin Finck     nStackDepth = 0;
83c2c66affSColin Finck     lpStackTop = NULL;
84c2c66affSColin Finck     lpStackBottom = NULL;
85c2c66affSColin Finck }
86c2c66affSColin Finck 
87c2c66affSColin Finck 
88c2c66affSColin Finck /*
89c2c66affSColin Finck  * destroy directory stack
90c2c66affSColin Finck  */
DestroyDirectoryStack(VOID)91c2c66affSColin Finck VOID DestroyDirectoryStack (VOID)
92c2c66affSColin Finck {
93c2c66affSColin Finck     while (nStackDepth)
94c2c66affSColin Finck         PopDirectory ();
95c2c66affSColin Finck }
96c2c66affSColin Finck 
97c2c66affSColin Finck 
GetDirectoryStackDepth(VOID)98c2c66affSColin Finck INT GetDirectoryStackDepth (VOID)
99c2c66affSColin Finck {
100c2c66affSColin Finck     return nStackDepth;
101c2c66affSColin Finck }
102c2c66affSColin Finck 
103c2c66affSColin Finck 
104c2c66affSColin Finck /*
105c2c66affSColin Finck  * pushd command
106c2c66affSColin Finck  */
CommandPushd(LPTSTR rest)107c2c66affSColin Finck INT CommandPushd (LPTSTR rest)
108c2c66affSColin Finck {
109c2c66affSColin Finck     TCHAR curPath[MAX_PATH];
110c2c66affSColin Finck 
111c2c66affSColin Finck     if (!_tcsncmp (rest, _T("/?"), 2))
112c2c66affSColin Finck     {
113c2c66affSColin Finck         ConOutResPuts(STRING_DIRSTACK_HELP1);
114c2c66affSColin Finck         return 0;
115c2c66affSColin Finck     }
116c2c66affSColin Finck 
117c2c66affSColin Finck     GetCurrentDirectory (MAX_PATH, curPath);
118c2c66affSColin Finck 
119c2c66affSColin Finck     if (rest[0] != _T('\0'))
120c2c66affSColin Finck     {
121c2c66affSColin Finck         if (!SetRootPath(NULL, rest))
122c2c66affSColin Finck             return 1;
123c2c66affSColin Finck     }
124c2c66affSColin Finck 
125c2c66affSColin Finck     return PushDirectory(curPath);
126c2c66affSColin Finck }
127c2c66affSColin Finck 
128c2c66affSColin Finck 
129c2c66affSColin Finck /*
130c2c66affSColin Finck  * popd command
131c2c66affSColin Finck  */
CommandPopd(LPTSTR rest)132c2c66affSColin Finck INT CommandPopd (LPTSTR rest)
133c2c66affSColin Finck {
134c2c66affSColin Finck     INT ret = 0;
135c2c66affSColin Finck     if (!_tcsncmp(rest, _T("/?"), 2))
136c2c66affSColin Finck     {
137c2c66affSColin Finck         ConOutResPuts(STRING_DIRSTACK_HELP2);
138c2c66affSColin Finck         return 0;
139c2c66affSColin Finck     }
140c2c66affSColin Finck 
141c2c66affSColin Finck     if (nStackDepth == 0)
142c2c66affSColin Finck         return 1;
143c2c66affSColin Finck 
144c2c66affSColin Finck     ret = _tchdir(lpStackTop->szPath) != 0;
145c2c66affSColin Finck     PopDirectory ();
146c2c66affSColin Finck 
147c2c66affSColin Finck     return ret;
148c2c66affSColin Finck }
149c2c66affSColin Finck 
150c2c66affSColin Finck 
151c2c66affSColin Finck /*
152c2c66affSColin Finck  * dirs command
153c2c66affSColin Finck  */
CommandDirs(LPTSTR rest)154c2c66affSColin Finck INT CommandDirs (LPTSTR rest)
155c2c66affSColin Finck {
156c2c66affSColin Finck     LPDIRENTRY lpDir;
157c2c66affSColin Finck 
158c2c66affSColin Finck     if (!_tcsncmp(rest, _T("/?"), 2))
159c2c66affSColin Finck     {
160c2c66affSColin Finck         ConOutResPuts(STRING_DIRSTACK_HELP3);
161c2c66affSColin Finck         return 0;
162c2c66affSColin Finck     }
163c2c66affSColin Finck 
164c2c66affSColin Finck     nErrorLevel = 0;
165c2c66affSColin Finck 
166c2c66affSColin Finck     lpDir = lpStackBottom;
167c2c66affSColin Finck 
168c2c66affSColin Finck     if (lpDir == NULL)
169c2c66affSColin Finck     {
170c2c66affSColin Finck         ConOutResPuts(STRING_DIRSTACK_HELP4);
171c2c66affSColin Finck         return 0;
172c2c66affSColin Finck     }
173c2c66affSColin Finck 
174c2c66affSColin Finck     while (lpDir != NULL)
175c2c66affSColin Finck     {
176c2c66affSColin Finck         ConOutPuts(lpDir->szPath);
177c2c66affSColin Finck         lpDir = lpDir->prev;
178c2c66affSColin Finck     }
179c2c66affSColin Finck 
180c2c66affSColin Finck     return 0;
181c2c66affSColin Finck }
182c2c66affSColin Finck 
183c2c66affSColin Finck #endif /* FEATURE_DIRECTORY_STACK */
184