Subversion Repositories SvarDOS

Rev

Rev 533 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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