update for HEAD-2003091401
[reactos.git] / subsys / system / cmd / date.c
1 /*
2  *  DATE.C - date internal command.
3  *
4  *
5  *  History:
6  *
7  *    08 Jul 1998 (John P. Price)
8  *        started.
9  *
10  *    20 Jul 1998 (John P. Price)
11  *        corrected number of days for December from 30 to 31.
12  *        (Thanx to Steffen Kaiser for bug report)
13  *
14  *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
15  *        added config.h include
16  *
17  *    29-Jul-1998 (Rob Lake)
18  *        fixed stand-alone mode.
19  *        Added Pacific C compatible dos_getdate functions
20  *
21  *    09-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
22  *        Added locale support
23  *
24  *    23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
25  *        Unicode and redirection safe!
26  *
27  *    04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
28  *        Fixed date input bug.
29  */
30
31 #include "config.h"
32
33 #ifdef INCLUDE_CMD_DATE
34
35 #include <windows.h>
36 #include <tchar.h>
37 #include <string.h>
38 #include <ctype.h>
39
40 #include "cmd.h"
41
42
43 static WORD awMonths[2][13] =
44 {
45         {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
46         {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
47 };
48
49
50 static VOID
51 PrintDateString (VOID)
52 {
53         switch (nDateFormat)
54         {
55                 case 0: /* mmddyy */
56                 default:
57                         ConOutPrintf (_T("\nEnter new date (mm%cdd%cyyyy): "),
58                                         cDateSeparator, cDateSeparator);
59                         break;
60
61                 case 1: /* ddmmyy */
62                         ConOutPrintf (_T("\nEnter new date (dd%cmm%cyyyy): "),
63                                           cDateSeparator, cDateSeparator);
64                         break;
65
66                 case 2: /* yymmdd */
67                         ConOutPrintf (_T("\nEnter new date (yyyy%cmm%cdd): "),
68                                           cDateSeparator, cDateSeparator);
69                         break;
70         }
71 }
72
73
74 static BOOL
75 ReadNumber (LPTSTR *s, LPWORD lpwValue)
76 {
77         if (_istdigit (**s))
78         {
79                 while (_istdigit (**s))
80                 {
81                         *lpwValue = *lpwValue * 10 + **s - _T('0');
82                         (*s)++;
83                 }
84                 return TRUE;
85         }
86         return FALSE;
87 }
88
89
90 static BOOL
91 ReadSeparator (LPTSTR *s)
92 {
93         if (**s == _T('/') || **s == _T('-') || **s == cDateSeparator)
94         {
95                 (*s)++;
96                 return TRUE;
97         }
98         return FALSE;
99 }
100
101
102 static BOOL
103 ParseDate (LPTSTR s)
104 {
105         SYSTEMTIME d;
106         unsigned char leap;
107         LPTSTR p = s;
108
109         if (!*s)
110                 return TRUE;
111
112         GetLocalTime (&d);
113
114         d.wYear = 0;
115         d.wDay = 0;
116         d.wMonth = 0;
117
118         switch (nDateFormat)
119         {
120                 case 0: /* mmddyy */
121                 default:
122                         if (!ReadNumber (&p, &d.wMonth))
123                                 return FALSE;
124                         if (!ReadSeparator (&p))
125                                 return FALSE;
126                         if (!ReadNumber (&p, &d.wDay))
127                                 return FALSE;
128                         if (!ReadSeparator (&p))
129                                 return FALSE;
130                         if (!ReadNumber (&p, &d.wYear))
131                                 return FALSE;
132                         break;
133
134                 case 1: /* ddmmyy */
135                         if (!ReadNumber (&p, &d.wDay))
136                                 return FALSE;
137                         if (!ReadSeparator (&p))
138                                 return FALSE;
139                         if (!ReadNumber (&p, &d.wMonth))
140                                 return FALSE;
141                         if (!ReadSeparator (&p))
142                                 return FALSE;
143                         if (!ReadNumber (&p, &d.wYear))
144                                 return FALSE;
145                         break;
146
147                 case 2: /* yymmdd */
148                         if (!ReadNumber (&p, &d.wYear))
149                                 return FALSE;
150                         if (!ReadSeparator (&p))
151                                 return FALSE;
152                         if (!ReadNumber (&p, &d.wMonth))
153                                 return FALSE;
154                         if (!ReadSeparator (&p))
155                                 return FALSE;
156                         if (!ReadNumber (&p, &d.wDay))
157                                 return FALSE;
158                         break;
159         }
160
161     /* if only entered two digits: */
162         /*   assume 2000's if value less than 80 */
163         /*   assume 1900's if value greater or equal 80 */
164         if (d.wYear <= 99)
165         {
166                 if (d.wYear >= 80)
167                         d.wYear = 1900 + d.wYear;
168                 else
169                         d.wYear = 2000 + d.wYear;
170         }
171
172         leap = (!(d.wYear % 4) && (d.wYear % 100)) || !(d.wYear % 400);
173
174         if ((d.wMonth >= 1 && d.wMonth <= 12) &&
175                 (d.wDay >= 1 && d.wDay <= awMonths[leap][d.wMonth]) &&
176                 (d.wYear >= 1980 && d.wYear <= 2099))
177         {
178                 SetLocalTime (&d);
179                 return TRUE;
180         }
181
182         return FALSE;
183 }
184
185
186 INT cmd_date (LPTSTR cmd, LPTSTR param)
187 {
188         LPTSTR *arg;
189         INT    argc;
190         INT    i;
191         BOOL   bPrompt = TRUE;
192         INT    nDateString = -1;
193
194         if (!_tcsncmp (param, _T("/?"), 2))
195         {
196                 ConOutPuts (_T("Displays or sets the date.\n\n"
197                                    "DATE [/T][date]\n\n"
198                                    "  /T    display only\n\n"
199                                    "Type DATE without parameters to display the current date setting and\n"
200                                    "a prompt for a new one.  Press ENTER to keep the same date."));
201                 return 0;
202         }
203
204         /* build parameter array */
205         arg = split (param, &argc, FALSE);
206
207         /* check for options */
208         for (i = 0; i < argc; i++)
209         {
210                 if (_tcsicmp (arg[i], _T("/t")) == 0)
211                         bPrompt = FALSE;
212                 if ((*arg[i] != _T('/')) && (nDateString == -1))
213                         nDateString = i;
214         }
215
216         if (nDateString == -1)
217                 PrintDate ();
218
219         if (!bPrompt)
220         {
221                 freep (arg);
222                 return 0;
223         }
224
225         if (nDateString == -1)
226         {
227                 while (TRUE)  /* forever loop */
228                 {
229                         TCHAR s[40];
230
231                         PrintDateString ();
232                         ConInString (s, 40);
233 #ifdef _DEBUG
234                         DebugPrintf (_T("\'%s\'\n"), s);
235 #endif
236                         while (*s && s[_tcslen (s) - 1] < _T(' '))
237                                 s[_tcslen (s) - 1] = _T('\0');
238                         if (ParseDate (s))
239                         {
240                                 freep (arg);
241                                 return 0;
242                         }
243                         ConErrPuts (_T("Invalid date."));
244                 }
245         }
246         else
247         {
248                 if (ParseDate (arg[nDateString]))
249                 {
250                         freep (arg);
251                         return 0;
252                 }
253                 ConErrPuts (_T("Invalid date."));
254         }
255
256         freep (arg);
257
258         return 0;
259 }
260 #endif
261