Subversion Repositories SvarDOS

Rev

Rev 501 | Rev 538 | Go to most recent revision | 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
 *
4
 * Copyright (C) 2021 Mateusz Viste
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)) {
144
    outputnl("Displays or sets the system time.");
145
    outputnl("");
146
    outputnl("TIME [time]");
147
    outputnl("");
148
    outputnl("Type TIME with no parameters to display the current time and a prompt for a");
149
    outputnl("new one. Press ENTER to keep the same time.");
533 mateuszvis 150
    return(CMD_OK);
427 mateuszvis 151
  }
152
 
153
  i = nls_getpatterns(nls);
154
  if (i != 0) {
155
    outputnl(doserr(i));
533 mateuszvis 156
    return(CMD_FAIL);
427 mateuszvis 157
  }
158
 
159
  /* display current time if no args */
160
  if (p->argc == 0) {
161
    /* get cur time */
162
    _asm {
163
      push ax
164
      push bx
165
      push cx
166
      push dx
167
 
168
      mov ah, 0x2c  /* DOS 1+ -- Query DOS Time */
169
      int 0x21      /* CH=hour CL=minutes DH=seconds DL=1/100sec */
170
      mov [ho], ch
171
      mov [mi], cl
172
      mov [se], dh
173
 
174
      pop dx
175
      pop cx
176
      pop bx
177
      pop ax
178
    }
179
    buff[0] = ' ';
180
    nls_format_time(buff + 1, ho, mi, se, nls);
181
    output("Current time is");
182
    outputnl(buff);
183
    ho = -1;
184
  } else { /* parse time if provided */
185
    if (cmd_time_parse(p->argv[0], &ho, &mi, &se, nls) != 0) {
186
      outputnl("Invalid time");
187
      ho = -1;
188
    }
189
  }
190
 
191
  /* ask for time if not provided or if input was malformed */
192
  while (ho < 0) {
193
    output("Enter new time:");
194
    output(" ");
195
    /* collect user input into buff */
196
    _asm {
197
      push ax
198
      push bx
199
      push dx
200
 
201
      mov ah, 0x0a   /* DOS 1+ -- Buffered String Input */
202
      mov bx, buff
203
      mov dx, bx
204
      mov al, 16
205
      mov [bx], al   /* max input length */
206
      mov al, 1
207
      mov [bx+1], al /* zero out the "previous entry" length */
208
      int 0x21
209
      /* terminate the string with a NULL terminator */
210
      xor ax, ax
211
      inc bx
212
      mov al, [bx] /* read length of input string */
213
      mov bx, ax
214
      add bx, dx
215
      mov [bx+2], ah
216
      /* output a \n */
217
      mov ah, 2
218
      mov dl, 0x0A
219
      int 0x21
220
 
221
      pop dx
222
      pop bx
223
      pop ax
224
    }
428 mateuszvis 225
    if (buff[1] == 0) break; /* empty string = do not change time */
427 mateuszvis 226
    if (cmd_time_parse(buff + 2, &ho, &mi, &se, nls) == 0) break;
227
    outputnl("Invalid time");
533 mateuszvis 228
    return(CMD_FAIL);
427 mateuszvis 229
  }
230
 
231
  if (ho >= 0) {
232
    /* set time */
233
    _asm {
234
      push ax
235
      push bx
236
      push cx
237
      push dx
238
 
239
      mov ah, 0x2d   /* DOS 1+ -- Set DOS Time */
240
      mov ch, [ho]   /* hour (0-23) */
241
      mov cl, [mi]   /* minutes (0-59) */
242
      mov dh, [se]   /* seconds (0-59) */
243
      mov dl, 0      /* 1/100th seconds (0-99) */
244
      int 0x21
245
 
246
      pop dx
247
      pop cx
248
      pop bx
249
      pop ax
250
    }
251
  }
252
 
533 mateuszvis 253
  return(CMD_OK);
427 mateuszvis 254
}