Copy wininet to branch
[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 lpDir = (LPDIRENTRY)malloc (sizeof (DIRENTRY));
41 if (!lpDir)
42 {
43 error_out_of_memory ();
44 return -1;
45 }
46
47 lpDir->prev = NULL;
48 if (lpStackTop == NULL)
49 {
50 lpDir->next = NULL;
51 lpStackBottom = lpDir;
52 }
53 else
54 {
55 lpDir->next = lpStackTop;
56 lpStackTop->prev = lpDir;
57 }
58 lpStackTop = lpDir;
59
60 lpDir->pszPath = (LPTSTR)malloc ((_tcslen(pszPath)+1)*sizeof(TCHAR));
61 if (!lpDir->pszPath)
62 {
63 free (lpDir);
64 error_out_of_memory ();
65 return -1;
66 }
67
68 _tcscpy (lpDir->pszPath, pszPath);
69
70 nStackDepth++;
71
72 return 0;
73 }
74
75
76 static VOID
77 PopDirectory (VOID)
78 {
79 LPDIRENTRY lpDir;
80
81 if (nStackDepth == 0)
82 return;
83
84 lpDir = lpStackTop;
85 lpStackTop = lpDir->next;
86 if (lpStackTop != NULL)
87 lpStackTop->prev = NULL;
88 else
89 lpStackBottom = NULL;
90
91 free (lpDir->pszPath);
92 free (lpDir);
93
94 nStackDepth--;
95 }
96
97
98 static VOID
99 GetDirectoryStackTop (LPTSTR pszPath)
100 {
101 if (lpStackTop)
102 _tcsncpy (pszPath, lpStackTop->pszPath, MAX_PATH);
103 else
104 *pszPath = _T('\0');
105 }
106
107
108 /*
109 * initialize directory stack
110 */
111 VOID InitDirectoryStack (VOID)
112 {
113 nStackDepth = 0;
114 lpStackTop = NULL;
115 lpStackBottom = NULL;
116 }
117
118
119 /*
120 * destroy directory stack
121 */
122 VOID DestroyDirectoryStack (VOID)
123 {
124 while (nStackDepth)
125 PopDirectory ();
126 }
127
128
129 INT GetDirectoryStackDepth (VOID)
130 {
131 return nStackDepth;
132 }
133
134
135 /*
136 * pushd command
137 */
138 INT CommandPushd (LPTSTR first, LPTSTR rest)
139 {
140 TCHAR curPath[MAX_PATH];
141 TCHAR newPath[MAX_PATH];
142 BOOL bChangePath = FALSE;
143 WCHAR szMsg[RC_STRING_MAX_SIZE];
144
145 if (!_tcsncmp (rest, _T("/?"), 2))
146 {
147 LoadString( GetModuleHandle(NULL), STRING_DIRSTACK_HELP1, (LPTSTR) szMsg,sizeof(szMsg));
148 ConOutPuts (_T((LPTSTR)szMsg));
149
150 return 0;
151 }
152
153 if (rest[0] != _T('\0'))
154 {
155 GetFullPathName (rest, MAX_PATH, newPath, NULL);
156 bChangePath = IsValidPathName (newPath);
157 }
158
159 GetCurrentDirectory (MAX_PATH, curPath);
160 if (PushDirectory (curPath))
161 return 0;
162
163 if (bChangePath)
164 SetCurrentDirectory (newPath);
165
166 return 0;
167 }
168
169
170 /*
171 * popd command
172 */
173 INT CommandPopd (LPTSTR first, LPTSTR rest)
174 {
175 TCHAR szPath[MAX_PATH];
176 WCHAR szMsg[RC_STRING_MAX_SIZE];
177
178 if (!_tcsncmp(rest, _T("/?"), 2))
179 {
180 LoadString( GetModuleHandle(NULL), STRING_DIRSTACK_HELP2, (LPTSTR) szMsg,sizeof(szMsg));
181 ConOutPuts (_T((LPTSTR)szMsg));
182
183 return 0;
184 }
185
186 if (GetDirectoryStackDepth () == 0)
187 return 0;
188
189 GetDirectoryStackTop (szPath);
190 PopDirectory ();
191
192 SetCurrentDirectory (szPath);
193
194 return 0;
195 }
196
197
198 /*
199 * dirs command
200 */
201 INT CommandDirs (LPTSTR first, LPTSTR rest)
202 {
203 LPDIRENTRY lpDir;
204 WCHAR szMsg[RC_STRING_MAX_SIZE];
205
206 if (!_tcsncmp(rest, _T("/?"), 2))
207 {
208 LoadString( GetModuleHandle(NULL), STRING_DIRSTACK_HELP3, (LPTSTR) szMsg,sizeof(szMsg));
209 ConOutPuts (_T((LPTSTR)szMsg));
210
211 return 0;
212 }
213
214
215 lpDir = lpStackBottom;
216
217 if (lpDir == NULL)
218 {
219 LoadString( GetModuleHandle(NULL), STRING_DIRSTACK_HELP4, (LPTSTR) szMsg,sizeof(szMsg));
220 ConOutPuts (_T((LPTSTR)szMsg));
221
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 */