SYSTEM_TIME_ZONE_INFORMATION added.
[reactos.git] / rosapps / 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 "config.h"
18
19 #ifdef FEATURE_DIRECTORY_STACK
20
21 #include <windows.h>
22 #include <tchar.h>
23 #include <string.h>
24 #include <stdlib.h>
25
26 #include "cmd.h"
27
28
29 typedef struct tagDIRENTRY
30 {
31 struct tagDIRENTRY *prev;
32 struct tagDIRENTRY *next;
33 LPTSTR pszPath;
34 } DIRENTRY, *LPDIRENTRY;
35
36
37 static INT nStackDepth;
38 static LPDIRENTRY lpStackTop;
39 static LPDIRENTRY lpStackBottom;
40
41
42 static INT
43 PushDirectory (LPTSTR pszPath)
44 {
45 LPDIRENTRY lpDir;
46
47 lpDir = (LPDIRENTRY)malloc (sizeof (DIRENTRY));
48 if (!lpDir)
49 {
50 error_out_of_memory ();
51 return -1;
52 }
53
54 lpDir->prev = NULL;
55 if (lpStackTop == NULL)
56 {
57 lpDir->next = NULL;
58 lpStackBottom = lpDir;
59 }
60 else
61 {
62 lpDir->next = lpStackTop;
63 lpStackTop->prev = lpDir;
64 }
65 lpStackTop = lpDir;
66
67 lpDir->pszPath = (LPTSTR)malloc ((_tcslen(pszPath)+1)*sizeof(TCHAR));
68 if (!lpDir->pszPath)
69 {
70 free (lpDir);
71 error_out_of_memory ();
72 return -1;
73 }
74
75 _tcscpy (lpDir->pszPath, pszPath);
76
77 nStackDepth++;
78
79 return 0;
80 }
81
82
83 static VOID
84 PopDirectory (VOID)
85 {
86 LPDIRENTRY lpDir;
87
88 if (nStackDepth == 0)
89 return;
90
91 lpDir = lpStackTop;
92 lpStackTop = lpDir->next;
93 if (lpStackTop != NULL)
94 lpStackTop->prev = NULL;
95 else
96 lpStackBottom = NULL;
97
98 free (lpDir->pszPath);
99 free (lpDir);
100
101 nStackDepth--;
102 }
103
104
105 static VOID
106 GetDirectoryStackTop (LPTSTR pszPath)
107 {
108 if (lpStackTop)
109 _tcsncpy (pszPath, lpStackTop->pszPath, MAX_PATH);
110 else
111 *pszPath = _T('\0');
112 }
113
114
115 /*
116 * initialize directory stack
117 */
118 VOID InitDirectoryStack (VOID)
119 {
120 nStackDepth = 0;
121 lpStackTop = NULL;
122 lpStackBottom = NULL;
123 }
124
125
126 /*
127 * destroy directory stack
128 */
129 VOID DestroyDirectoryStack (VOID)
130 {
131 while (nStackDepth)
132 PopDirectory ();
133 }
134
135
136 INT GetDirectoryStackDepth (VOID)
137 {
138 return nStackDepth;
139 }
140
141
142 /*
143 * pushd command
144 */
145 INT CommandPushd (LPTSTR first, LPTSTR rest)
146 {
147 TCHAR curPath[MAX_PATH];
148 TCHAR newPath[MAX_PATH];
149 BOOL bChangePath = FALSE;
150
151 if (!_tcsncmp (rest, _T("/?"), 2))
152 {
153 ConOutPuts (_T("Stores the current directory for use by the POPD command, then\n"
154 "changes to the specified directory.\n\n"
155 "PUSHD [path | ..]\n\n"
156 " path Specifies the directory to make the current directory"));
157 return 0;
158 }
159
160 if (rest[0] != _T('\0'))
161 {
162 GetFullPathName (rest, MAX_PATH, newPath, NULL);
163 bChangePath = IsValidPathName (newPath);
164 }
165
166 GetCurrentDirectory (MAX_PATH, curPath);
167 if (PushDirectory (curPath))
168 return 0;
169
170 if (bChangePath)
171 SetCurrentDirectory (newPath);
172
173 return 0;
174 }
175
176
177 /*
178 * popd command
179 */
180 INT CommandPopd (LPTSTR first, LPTSTR rest)
181 {
182 TCHAR szPath[MAX_PATH];
183
184 if (!_tcsncmp(rest, _T("/?"), 2))
185 {
186 ConOutPuts (_T("Changes to the directory stored by the PUSHD command.\n\n"
187 "POPD"));
188 return 0;
189 }
190
191 if (GetDirectoryStackDepth () == 0)
192 return 0;
193
194 GetDirectoryStackTop (szPath);
195 PopDirectory ();
196
197 SetCurrentDirectory (szPath);
198
199 return 0;
200 }
201
202
203 /*
204 * dirs command
205 */
206 INT CommandDirs (LPTSTR first, LPTSTR rest)
207 {
208 LPDIRENTRY lpDir;
209
210 if (!_tcsncmp(rest, _T("/?"), 2))
211 {
212 ConOutPuts (_T("Prints the contents of the directory stack.\n"
213 "\n"
214 "DIRS"));
215 return 0;
216 }
217
218
219 lpDir = lpStackBottom;
220
221 if (lpDir == NULL)
222 {
223 ConOutPuts (_T("Directory stack empty"));
224 return 0;
225 }
226
227 while (lpDir != NULL)
228 {
229 ConOutPuts (lpDir->pszPath);
230
231 lpDir = lpDir->prev;
232 }
233
234 return 0;
235 }
236
237 #endif /* FEATURE_DIRECTORY_STACK */