0,0 → 1,225 |
/* This file is part of the SvarCOM project and is published under the terms |
* of the MIT license. |
* |
* Copyright (C) 2021-2022 Mateusz Viste |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
* DEALINGS IN THE SOFTWARE. |
*/ |
|
/* |
* date [date] |
*/ |
|
|
/* parse a NULL-terminated string int hour, minutes and seconds, returns 0 on success |
* valid inputs: 0, 7, 5:5, 23:23, 17:54:45, 9p, 9:05, ... |
*/ |
static int cmd_date_parse(const char *s, unsigned short *year, unsigned char *mo, unsigned char *dy, struct nls_patterns *nls) { |
unsigned short i; |
const char *ptrs[2] = {NULL, NULL}; |
|
*year = 0; |
*mo = 0; |
*dy = 0; |
|
/* validate input - must contain only chars 0-9 and time separator */ |
for (i = 0; s[i] != 0; i++) { |
switch (s[i]) { |
case '0': |
case '1': |
case '2': |
case '3': |
case '4': |
case '5': |
case '6': |
case '7': |
case '8': |
case '9': |
break; |
default: |
if ((s[i] != nls->datesep[0]) || (i == 0)) return(-1); |
if (ptrs[0] == NULL) { |
ptrs[0] = s + i + 1; |
} else if (ptrs[1] == NULL) { |
ptrs[1] = s + i + 1; |
} else { /* too many separators */ |
return(-1); |
} |
break; |
} |
} |
|
/* did I get all separators? */ |
if ((ptrs[0] == NULL) || (ptrs[1] == NULL)) goto FAIL; |
|
/* d/m/y order depends on NLS settings */ |
switch (nls->dateformat) { |
case 0: /* m/d/y */ |
atous(&i, s); |
*mo = i; |
atous(&i, ptrs[0]); |
*dy = i; |
atous(year, ptrs[1]); |
break; |
case 1: /* d/m/y */ |
atous(&i, s); |
*dy = i; |
atous(&i, ptrs[0]); |
*mo = i; |
atous(year, ptrs[1]); |
break; |
default: /* y/m/d */ |
atous(year, s); |
atous(&i, ptrs[0]); |
*mo = i; |
atous(&i, ptrs[1]); |
*dy = i; |
break; |
} |
|
return(0); |
|
FAIL: |
*year = 0; |
return(-1); |
} |
|
|
/* set system date, return 0 on success */ |
static int cmd_date_set(unsigned short year, unsigned char mo, unsigned char dy) { |
_asm { |
push ax |
push bx |
push cx |
push dx |
|
mov ax, 0x2b00 /* DOS 1+ -- Set DOS Date */ |
mov cx, [year] /* year (1980-2099) */ |
mov dh, [mo] /* month (1-12) */ |
mov dl, [dy] /* day (1-31) */ |
int 0x21 /* AL = 0 on success */ |
cmp al, 0 |
je DONE |
mov [year], 0 |
DONE: |
|
pop dx |
pop cx |
pop bx |
pop ax |
} |
|
if (year == 0) return(-1); |
return(0); |
} |
|
|
static enum cmd_result cmd_date(struct cmd_funcparam *p) { |
struct nls_patterns *nls = (void *)(p->BUFFER); |
char *buff = p->BUFFER + sizeof(*nls); |
unsigned short i; |
unsigned short year = 0; |
unsigned char mo, dy; |
|
if (cmd_ishlp(p)) { |
nls_outputnl(32,0); /* "Displays or sets the system date."); */ |
outputnl(""); |
nls_outputnl(32,1); /* "DATE [date]" */ |
outputnl(""); |
nls_outputnl(32,2); /* "Type DATE with no parameters to display the (...)" */ |
return(CMD_OK); |
} |
|
i = nls_getpatterns(nls); |
if (i != 0) { |
nls_outputnl_doserr(i); |
return(CMD_FAIL); |
} |
|
/* display current date if no args */ |
if (p->argc == 0) { |
/* get cur date */ |
_asm { |
push ax |
push cx |
push dx |
|
mov ah, 0x2a /* DOS 1+ -- Query DOS Date */ |
int 0x21 /* CX=year DH=month DL=day */ |
mov [year], cx |
mov [mo], dh |
mov [dy], dl |
|
pop dx |
pop cx |
pop ax |
} |
buff[0] = ' '; |
nls_format_date(buff + 1, year, mo, dy, nls); |
nls_output(32,4); /* "Current date is" */ |
outputnl(buff); |
year = 0; |
} else { /* parse date if provided */ |
if ((cmd_date_parse(p->argv[0], &year, &mo, &dy, nls) != 0) || (cmd_date_set(year, mo, dy) != 0)) { |
nls_outputnl(32,3); /* "Invalid date" */ |
year = 0; |
} |
} |
|
/* ask for date if not provided or if input was malformed */ |
while (year == 0) { |
nls_output(32,5); /* "Enter new date:" */ |
output(" "); |
/* collect user input into buff */ |
_asm { |
push ax |
push bx |
push dx |
|
mov ah, 0x0a /* DOS 1+ -- Buffered String Input */ |
mov bx, buff |
mov dx, bx |
mov al, 16 |
mov [bx], al /* max input length */ |
mov al, 1 |
mov [bx+1], al /* zero out the "previous entry" length */ |
int 0x21 |
/* terminate the string with a NULL terminator */ |
xor ax, ax |
inc bx |
mov al, [bx] /* read length of input string */ |
mov bx, ax |
add bx, dx |
mov [bx+2], ah |
/* output a \n */ |
mov ah, 2 |
mov dl, 0x0A |
int 0x21 |
|
pop dx |
pop bx |
pop ax |
} |
if (buff[1] == 0) break; /* empty string = no date change */ |
if ((cmd_date_parse(buff + 2, &year, &mo, &dy, nls) == 0) && (cmd_date_set(year, mo, dy) == 0)) break; |
nls_outputnl(32,3); /* "Invalid date" */ |
} |
|
return(CMD_OK); |
} |