move network tools
[reactos.git] / reactos / subsys / system / cmd / dirstack.c
1 /*
2 * DIRSTACK.C - pushd / pop (directory stack) internal commands.
3 *
4 *
5 * History:
6 *
7 * 14-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
8 * Implemented PUSHD and POPD command.
9 *
10 * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
11 * Unicode and redirection safe!
12 *
13 * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
14 * Added DIRS command.
15 */
16
17 #include <precomp.h>
18 #include "resource.h"
19
20 #ifdef FEATURE_DIRECTORY_STACK
21
22 typedef struct tagDIRENTRY
23 {
24 struct tagDIRENTRY *prev;
25 struct tagDIRENTRY *next;
26 LPTSTR pszPath;
27 } DIRENTRY, *LPDIRENTRY;
28
29
30 static INT nStackDepth;
31 static LPDIRENTRY lpStackTop;
32 static LPDIRENTRY lpStackBottom;
33
34
35 static INT
36 PushDirectory (LPTSTR pszPath)
37 {
38 LPDIRENTRY lpDir;
39
40 nErrorLevel = 0;
41
42 lpDir = (LPDIRENTRY)malloc (sizeof (DIRENTRY));
43 if (!lpDir)
44 {
45 error_out_of_memory ();
46 return -1;
47 }
48
49 lpDir->prev = NULL;
50 if (lpStackTop == NULL)
51 {
52 lpDir->next = NULL;
53 lpStackBottom = lpDir;
54 }
55 else
56 {
57 lpDir->next = lpStackTop;
58 lpStackTop->prev = lpDir;
59 }
60 lpStackTop = lpDir;
61
62 lpDir->pszPath = (LPTSTR)malloc ((_tcslen(pszPath)+1)*sizeof(TCHAR));
63 if (!lpDir->pszPath)
64 {
65 free (lpDir);
66 error_out_of_memory ();
67 return -1;
68 }
69
70 _tcscpy (lpDir->pszPath, pszPath);
71
72 nStackDepth++;
73
74 return 0;
75 }
76
77
78 static VOID
79 PopDirectory (VOID)
80 {
81 LPDIRENTRY lpDir;
82
83 nErrorLevel = 0;
84
85 if (nStackDepth == 0)
86 return;
87
88 lpDir = lpStackTop;
89 lpStackTop = lpDir->next;
90 if (lpStackTop != NULL)
91 lpStackTop->prev = NULL;
92 else
93 lpStackBottom = NULL;
94
95 free (lpDir->pszPath);
96 free (lpDir);
97
98 nStackDepth--;
99 }
100
101
102 static VOID
103 GetDirectoryStackTop (LPTSTR pszPath)
104 {
105 nErrorLevel = 0;
106
107 if (lpStackTop)
108 _tcsncpy (pszPath, lpStackTop->pszPath, MAX_PATH);
109 else
110 *pszPath = _T('\0');
111 }
112
113
114 /*
115 * initialize directory stack
116 */
117 VOID InitDirectoryStack (VOID)
118 {
119 nStackDepth = 0;
120 lpStackTop = NULL;
121 lpStackBottom = NULL;
122 }
123
124
125 /*
126 * destroy directory stack
127 */
128 VOID DestroyDirectoryStack (VOID)
129 {
130 while (nStackDepth)
131 PopDirectory ();
132 }
133
134
135 INT GetDirectoryStackDepth (VOID)
136 {
137 return nStackDepth;
138 }
139
140
141 /*
142 * pushd command
143 */
144 INT CommandPushd (LPTSTR first, LPTSTR rest)
145 {
146 TCHAR curPath[MAX_PATH];
147 TCHAR newPath[MAX_PATH];
148 BOOL bChangePath = FALSE;
149
150 if (!_tcsncmp (rest, _T("/?"), 2))
151 {
152 ConOutResPuts(STRING_DIRSTACK_HELP1);
153 return 0;
154 }
155
156 nErrorLevel = 0;
157
158 if (rest[0] != _T('\0'))
159 {
160 GetFullPathName (rest, MAX_PATH, newPath, NULL);
161 bChangePath = IsValidPathName (newPath);
162 }
163
164 GetCurrentDirectory (MAX_PATH, curPath);
165 if (PushDirectory (curPath))
166 return 0;
167
168 if (bChangePath)
169 SetCurrentDirectory (newPath);
170
171 return 0;
172 }
173
174
175 /*
176 * popd command
177 */
178 INT CommandPopd (LPTSTR first, LPTSTR rest)
179 {
180 TCHAR szPath[MAX_PATH];
181
182 if (!_tcsncmp(rest, _T("/?"), 2))
183 {
184 ConOutResPuts(STRING_DIRSTACK_HELP2);
185 return 0;
186 }
187
188 nErrorLevel = 0;
189
190 if (GetDirectoryStackDepth () == 0)
191 return 0;
192
193 GetDirectoryStackTop (szPath);
194 PopDirectory ();
195
196 SetCurrentDirectory (szPath);
197
198 return 0;
199 }
200
201
202 /*
203 * dirs command
204 */
205 INT CommandDirs (LPTSTR first, LPTSTR rest)
206 {
207 LPDIRENTRY lpDir;
208
209 if (!_tcsncmp(rest, _T("/?"), 2))
210 {
211 ConOutResPuts(STRING_DIRSTACK_HELP3);
212 return 0;
213 }
214
215 nErrorLevel = 0;
216
217 lpDir = lpStackBottom;
218
219 if (lpDir == NULL)
220 {
221 ConOutResPuts(STRING_DIRSTACK_HELP4);
222 return 0;
223 }
224
225 while (lpDir != NULL)
226 {
227 ConOutPuts (lpDir->pszPath);
228
229 lpDir = lpDir->prev;
230 }
231
232 return 0;
233 }
234
235 #endif /* FEATURE_DIRECTORY_STACK */