xref: /reactos/base/shell/cmd/dirstack.c (revision 8a978a17)
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
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
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  */
80 VOID InitDirectoryStack (VOID)
81 {
82     nStackDepth = 0;
83     lpStackTop = NULL;
84     lpStackBottom = NULL;
85 }
86 
87 
88 /*
89  * destroy directory stack
90  */
91 VOID DestroyDirectoryStack (VOID)
92 {
93     while (nStackDepth)
94         PopDirectory ();
95 }
96 
97 
98 INT GetDirectoryStackDepth (VOID)
99 {
100     return nStackDepth;
101 }
102 
103 
104 /*
105  * pushd command
106  */
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  */
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  */
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