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