Subversion Repositories SvarDOS

Rev

Rev 538 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
427 mateuszvis 1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
3
 *
989 mateusz.vi 4
 * Copyright (C) 2021-2022 Mateusz Viste
427 mateuszvis 5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
/*
26
 * time [time]
27
 */
28
 
29
 
30
/* read a one or two digit number and write it to buff */
31
static int cmd_time_get_item(char *buff, const char *s) {
32
  unsigned short i;
33
 
34
  for (i = 0; i < 3; i++) {
35
    if ((s[i] < '0') || (s[i] > '9')) {
36
      buff[i] = 0;
37
      return(0);
38
    }
39
    buff[i] = s[i];
40
  }
41
 
42
  /* err */
43
  *buff = 0;
44
  return(-1);
45
}
46
 
47
 
48
/* parse a NULL-terminated string int hour, minutes and seconds, returns 0 on success
49
 * valid inputs: 0, 7, 5:5, 23:23, 17:54:45, 9p, 9:05, ...
50
 */
51
static int cmd_time_parse(const char *s, signed char *ho, signed char *mi, signed char *se, struct nls_patterns *nls) {
52
  unsigned short i;
53
  const char *ptrs[2] = {NULL, NULL}; /* minutes, seconds */
54
  char buff[3];
55
  char ampm = 0;
56
 
57
  *ho = -1;
58
  *mi = 0;
59
  *se = 0;
60
 
61
  /* validate input - must contain only chars 0-9, time separator and 'a' or 'p' */
62
  for (i = 0; s[i] != 0; i++) {
63
    switch (s[i]) {
64
      case '0':
65
      case '1':
66
      case '2':
67
      case '3':
68
      case '4':
69
      case '5':
70
      case '6':
71
      case '7':
72
      case '8':
73
      case '9':
74
        break;
75
      case 'a':
76
      case 'A':
77
      case 'p':
78
      case 'P':
79
        /* these can be only at last position and never at the first */
80
        if ((s[i + 1] != 0) || (i == 0)) return(-1);
81
        ampm = s[i];
82
        if (ampm >= 'a') ampm -= ('a' - 'A');
83
        break;
84
      default:
85
        if ((s[i] != nls->timesep[0]) || (i == 0)) return(-1);
86
        if (ptrs[0] == NULL) {
87
          ptrs[0] = s + i + 1;
88
        } else if (ptrs[1] == NULL) {
89
          ptrs[1] = s + i + 1;
90
        } else { /* too many separators */
91
          return(-1);
92
        }
93
        break;
94
    }
95
  }
96
 
97
  /* read hour */
98
  if (cmd_time_get_item(buff, s) != 0) goto FAIL;
99
  if (atous(&i, buff) != 0) goto FAIL;
100
  *ho = i;
101
 
102
  /* if minutes provided, read them */
103
  if (ptrs[0] != NULL) {
104
    if (cmd_time_get_item(buff, ptrs[0]) != 0) goto FAIL;
105
    if (atous(&i, buff) != 0) goto FAIL;
106
    *mi = i;
107
  }
108
 
429 mateuszvis 109
  /* if seconds provided, read them */
427 mateuszvis 110
  if (ptrs[1] != NULL) {
111
    if (cmd_time_get_item(buff, ptrs[1]) != 0) goto FAIL;
112
    if (atous(&i, buff) != 0) goto FAIL;
113
    *se = i;
114
  }
115
 
116
  /* validate ranges */
117
  if ((*ho > 23) || (*mi > 59) || (*se > 59)) goto FAIL;
118
 
119
  /* am? */
120
  if ((ampm == 'A') && (*ho > 12)) goto FAIL;
121
  if ((ampm == 'A') && (*ho == 12)) *ho = 0; /* 12:00am is 00:00 (midnight) */
122
 
123
  /* pm? */
124
  if (ampm == 'P') {
125
    if (*ho > 12) goto FAIL;
126
    if (*ho < 12) *ho += 12;
127
  }
128
 
129
  return(0);
130
 
131
  FAIL:
132
  *ho = -1;
133
  return(-1);
134
}
135
 
136
 
533 mateuszvis 137
static enum cmd_result cmd_time(struct cmd_funcparam *p) {
427 mateuszvis 138
  struct nls_patterns *nls = (void *)(p->BUFFER);
501 mateuszvis 139
  char *buff = p->BUFFER + sizeof(*nls);
427 mateuszvis 140
  unsigned short i;
141
  signed char ho = -1, mi = -1, se = -1;
142
 
143
  if (cmd_ishlp(p)) {
989 mateusz.vi 144
    nls_outputnl(22,0); /* "Displays or sets the system time." */
427 mateuszvis 145
    outputnl("");
989 mateusz.vi 146
    nls_outputnl(22,1); /* "TIME [time]" */
427 mateuszvis 147
    outputnl("");
989 mateusz.vi 148
    nls_outputnl(22,2); /* "Type TIME with no parameters to display the current time and (...)" */
533 mateuszvis 149
    return(CMD_OK);
427 mateuszvis 150
  }
151
 
152
  i = nls_getpatterns(nls);
153
  if (i != 0) {
538 mateuszvis 154
    nls_outputnl_doserr(i);
533 mateuszvis 155
    return(CMD_FAIL);
427 mateuszvis 156
  }
157
 
158
  /* display current time if no args */
159
  if (p->argc == 0) {
160
    /* get cur time */
161
    _asm {
162
      push ax
163
      push bx
164
      push cx
165
      push dx
166
 
167
      mov ah, 0x2c  /* DOS 1+ -- Query DOS Time */
168
      int 0x21      /* CH=hour CL=minutes DH=seconds DL=1/100sec */
169
      mov [ho], ch
170
      mov [mi], cl
171
      mov [se], dh
172
 
173
      pop dx
174
      pop cx
175
      pop bx
176
      pop ax
177
    }
178
    buff[0] = ' ';
179
    nls_format_time(buff + 1, ho, mi, se, nls);
989 mateusz.vi 180
    nls_output(22,3); /* "Current time is" */
427 mateuszvis 181
    outputnl(buff);
182
    ho = -1;
183
  } else { /* parse time if provided */
184
    if (cmd_time_parse(p->argv[0], &ho, &mi, &se, nls) != 0) {
989 mateusz.vi 185
      nls_outputnl(22,4); /* "Invalid time" */
427 mateuszvis 186
      ho = -1;
187
    }
188
  }
189
 
190
  /* ask for time if not provided or if input was malformed */
191
  while (ho < 0) {
989 mateusz.vi 192
    nls_output(22,5); /* "Enter new time:" */
427 mateuszvis 193
    output(" ");
194
    /* collect user input into buff */
195
    _asm {
196
      push ax
197
      push bx
198
      push dx
199
 
200
      mov ah, 0x0a   /* DOS 1+ -- Buffered String Input */
201
      mov bx, buff
202
      mov dx, bx
203
      mov al, 16
204
      mov [bx], al   /* max input length */
205
      mov al, 1
206
      mov [bx+1], al /* zero out the "previous entry" length */
207
      int 0x21
208
      /* terminate the string with a NULL terminator */
209
      xor ax, ax
210
      inc bx
211
      mov al, [bx] /* read length of input string */
212
      mov bx, ax
213
      add bx, dx
214
      mov [bx+2], ah
215
      /* output a \n */
216
      mov ah, 2
217
      mov dl, 0x0A
218
      int 0x21
219
 
220
      pop dx
221
      pop bx
222
      pop ax
223
    }
428 mateuszvis 224
    if (buff[1] == 0) break; /* empty string = do not change time */
427 mateuszvis 225
    if (cmd_time_parse(buff + 2, &ho, &mi, &se, nls) == 0) break;
989 mateusz.vi 226
    nls_outputnl(22,4); /* "Invalid time" */
533 mateuszvis 227
    return(CMD_FAIL);
427 mateuszvis 228
  }
229
 
230
  if (ho >= 0) {
231
    /* set time */
232
    _asm {
233
      push ax
234
      push bx
235
      push cx
236
      push dx
237
 
238
      mov ah, 0x2d   /* DOS 1+ -- Set DOS Time */
239
      mov ch, [ho]   /* hour (0-23) */
240
      mov cl, [mi]   /* minutes (0-59) */
241
      mov dh, [se]   /* seconds (0-59) */
242
      mov dl, 0      /* 1/100th seconds (0-99) */
243
      int 0x21
244
 
245
      pop dx
246
      pop cx
247
      pop bx
248
      pop ax
249
    }
250
  }
251
 
533 mateuszvis 252
  return(CMD_OK);
427 mateuszvis 253
}