Use FileGetString instead of ReadFile, because ReadFile doesn't return a null termina...
[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
144 if (!_tcsncmp (rest, _T("/?"), 2))
145 {
146 ConOutResPuts(STRING_DIRSTACK_HELP1);
147 return 0;
148 }
149
150 if (rest[0] != _T('\0'))
151 {
152 GetFullPathName (rest, MAX_PATH, newPath, NULL);
153 bChangePath = IsValidPathName (newPath);
154 }
155
156 GetCurrentDirectory (MAX_PATH, curPath);
157 if (PushDirectory (curPath))
158 return 0;
159
160 if (bChangePath)
161 SetCurrentDirectory (newPath);
162
163 return 0;
164 }
165
166
167 /*
168 * popd command
169 */
170 INT CommandPopd (LPTSTR first, LPTSTR rest)
171 {
172 TCHAR szPath[MAX_PATH];
173
174 if (!_tcsncmp(rest, _T("/?"), 2))
175 {
176 ConOutResPuts(STRING_DIRSTACK_HELP2);
177 return 0;
178 }
179
180 if (GetDirectoryStackDepth () == 0)
181 return 0;
182
183 GetDirectoryStackTop (szPath);
184 PopDirectory ();
185
186 SetCurrentDirectory (szPath);
187
188 return 0;
189 }
190
191
192 /*
193 * dirs command
194 */
195 INT CommandDirs (LPTSTR first, LPTSTR rest)
196 {
197 LPDIRENTRY lpDir;
198
199 if (!_tcsncmp(rest, _T("/?"), 2))
200 {
201 ConOutResPuts(STRING_DIRSTACK_HELP3);
202 return 0;
203 }
204
205
206 lpDir = lpStackBottom;
207
208 if (lpDir == NULL)
209 {
210 ConOutResPuts(STRING_DIRSTACK_HELP4);
211 return 0;
212 }
213
214 while (lpDir != NULL)
215 {
216 ConOutPuts (lpDir->pszPath);
217
218 lpDir = lpDir->prev;
219 }
220
221 return 0;
222 }
223
224 #endif /* FEATURE_DIRECTORY_STACK */