1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1997,1998 by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 /*LINTLIBRARY*/ 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <ctype.h> 37 #include <limits.h> 38 #include <sys/types.h> 39 #include <stdlib.h> 40 #include "libadm.h" 41 42 static int fmtcheck(char *); 43 44 #define PROMPT "Enter the time of day" 45 #define ERRMSG "Please enter the time of day. Format is" 46 #define DEFAULT "%H:%M" 47 48 #define TLEN 3 49 #define LH 00 50 #define UH 23 51 #define USH 12 52 #define LM 00 53 #define UM 59 54 #define LS 00 55 #define US 59 56 #define DELIM1 ':' 57 #define BLANK ' ' 58 #define TAB ' ' 59 60 static void 61 setmsg(char *msg, char *fmt) 62 { 63 if (fmt == NULL) 64 fmt = DEFAULT; 65 (void) sprintf(msg, "%s <%s>.", ERRMSG, fmt); 66 } 67 68 static char * 69 p_ndig(char *string, int *value) 70 { 71 char *ptr; 72 int accum = 0; 73 int n = 2; 74 75 if (!string) 76 return (0); 77 for (ptr = string; *ptr && n > 0; n--, ptr++) { 78 if (! isdigit((unsigned char)*ptr)) 79 return (NULL); 80 accum = (10 * accum) + (*ptr - '0'); 81 } 82 if (n) 83 return (NULL); 84 *value = accum; 85 return (ptr); 86 } 87 88 static char * 89 p_time(char *string, int llim, int ulim) 90 { 91 char *ptr; 92 int begin = -1; 93 if (!(ptr = p_ndig(string, &begin))) 94 return (NULL); 95 if (begin >= llim && begin <= ulim) 96 return (ptr); 97 else return (NULL); 98 } 99 100 /* p_meridian will parse the string for the meridian - AM/PM or am/pm */ 101 102 static char * 103 p_meridian(char *string) 104 { 105 static char *middle[] = { "AM", "PM", "am", "pm" }; 106 int legit, n; 107 char mid[TLEN]; 108 109 legit = 0; 110 n = 0; 111 mid[2] = '\0'; 112 (void) sscanf(string, "%2s", mid); 113 while (!(legit) && (n < 4)) { 114 if ((strncmp(mid, middle[n], 2)) == 0) 115 legit = 1; /* found legitimate string */ 116 n++; 117 } 118 if (legit) 119 return (string+2); 120 return (NULL); 121 } 122 123 static char * 124 p_delim(char *string, char dchoice) 125 { 126 char dlm; 127 128 if (! string) 129 return (NULL); 130 (void) sscanf(string, "%1c", &dlm); 131 return ((dlm == dchoice) ? string + 1 : NULL); 132 } 133 134 int 135 cktime_val(char *fmt, char *input) 136 { 137 char ltrl, dfl; 138 int valid = 1; /* time of day string is valid for format */ 139 140 if ((fmt != NULL) && (fmtcheck(fmt) == 1)) 141 return (4); 142 143 if (fmt == NULL) 144 fmt = DEFAULT; 145 ltrl = '\0'; 146 while (*fmt && valid) { 147 if ((*fmt) == '%') { 148 switch (*++fmt) { 149 case 'H': 150 input = p_time(input, LH, UH); 151 if (!input) 152 valid = 0; 153 break; 154 155 case 'M': 156 input = p_time(input, LM, UM); 157 if (!input) 158 valid = 0; 159 break; 160 161 case 'S': 162 input = p_time(input, LS, US); 163 if (!input) 164 valid = 0; 165 break; 166 167 case 'T': 168 input = p_time(input, LH, UH); 169 if (!input) { 170 valid = 0; 171 break; 172 } 173 174 input = p_delim(input, DELIM1); 175 if (!input) { 176 valid = 0; 177 break; 178 } 179 input = p_time(input, LM, UM); 180 if (!input) { 181 valid = 0; 182 break; 183 } 184 input = p_delim(input, DELIM1); 185 if (!input) { 186 valid = 0; 187 break; 188 } 189 input = p_time(input, LS, US); 190 if (!input) 191 valid = 0; 192 break; 193 194 case 'R': 195 input = p_time(input, LH, UH); 196 if (!input) { 197 valid = 0; 198 break; 199 } 200 input = p_delim(input, DELIM1); 201 if (!input) { 202 valid = 0; 203 break; 204 } 205 input = p_time(input, LM, UM); 206 if (!input) { 207 valid = 0; 208 break; 209 } 210 break; 211 212 case 'r': 213 input = p_time(input, LH, USH); 214 if (!input) { 215 valid = 0; 216 break; 217 } 218 input = p_delim(input, DELIM1); 219 if (!input) { 220 valid = 0; 221 break; 222 } 223 input = p_time(input, LM, UM); 224 if (!input) { 225 valid = 0; 226 break; 227 } 228 input = p_delim(input, DELIM1); 229 if (!input) { 230 valid = 0; 231 break; 232 } 233 input = p_time(input, LS, US); 234 if (!input) { 235 valid = 0; 236 break; 237 } 238 input = p_delim(input, BLANK); 239 if (!input) { 240 valid = 0; 241 break; 242 } 243 input = p_meridian(input); 244 if (!input) 245 valid = 0; 246 break; 247 248 case 'I': 249 input = p_time(input, LH, USH); 250 if (!input) 251 valid = 0; 252 break; 253 254 case 'p': 255 input = p_meridian(input); 256 if (!input) 257 valid = 0; 258 break; 259 260 default: 261 (void) sscanf(input++, "%1c", <rl); 262 } 263 } else { 264 dfl = '\0'; 265 (void) sscanf(input, "%1c", &dfl); 266 input++; 267 } 268 fmt++; 269 } 270 271 if (!(*fmt) && (input) && (*input)) 272 valid = 0; 273 274 return ((valid == 0)); 275 } 276 277 int 278 cktime_err(char *fmt, char *error) 279 { 280 char defmesg[128]; 281 282 if ((fmt != NULL) && (fmtcheck(fmt) == 1)) 283 return (4); 284 setmsg(defmesg, fmt); 285 puterror(stdout, defmesg, error); 286 return (0); 287 } 288 289 int 290 cktime_hlp(char *fmt, char *help) 291 { 292 char defmesg[128]; 293 294 if ((fmt != NULL) && (fmtcheck(fmt) == 1)) 295 return (4); 296 setmsg(defmesg, fmt); 297 puthelp(stdout, defmesg, help); 298 return (0); 299 } 300 301 /* 302 * A little state machine that checks out the format to 303 * make sure it is acceptable. 304 * return value 1: NG 305 * return value 0: OK 306 */ 307 int 308 fmtcheck(char *fmt) 309 { 310 int percent = 0; 311 312 while (*fmt) { 313 switch (*fmt++) { 314 case '%': /* previous state must be start or letter */ 315 if (percent == 0) 316 percent = 1; 317 else 318 return (1); 319 break; 320 case 'H': /* previous state must be "%" */ 321 case 'M': 322 case 'S': 323 case 'T': 324 case 'R': 325 case 'r': 326 case 'I': 327 case 'p': 328 if (percent == 1) 329 percent = 0; 330 else 331 return (1); 332 break; 333 case TAB: /* previous state must be start or letter */ 334 case BLANK: 335 case DELIM1: 336 if (percent == 1) 337 return (1); 338 break; 339 default: 340 return (1); 341 } 342 } 343 return (percent); 344 } 345 346 int 347 cktime(char *tod, char *fmt, char *defstr, char *error, char *help, 348 char *prompt) 349 { 350 char input[MAX_INPUT], 351 defmesg[128]; 352 353 if ((fmt != NULL) && (fmtcheck(fmt) == 1)) 354 return (4); 355 356 if (fmt == NULL) 357 fmt = DEFAULT; 358 setmsg(defmesg, fmt); 359 if (!prompt) 360 prompt = "Enter a time of day"; 361 362 start: 363 putprmpt(stderr, prompt, NULL, defstr); 364 if (getinput(input)) 365 return (1); 366 367 if (!strlen(input)) { 368 if (defstr) { 369 (void) strcpy(tod, defstr); 370 return (0); 371 } 372 puterror(stderr, defmesg, error); 373 goto start; 374 } 375 if (strcmp(input, "?") == 0) { 376 puthelp(stderr, defmesg, help); 377 goto start; 378 } 379 if (ckquit && (strcmp(input, "q") == 0)) 380 return (3); 381 382 if (cktime_val(fmt, input)) { 383 puterror(stderr, defmesg, error); 384 goto start; 385 } 386 (void) strcpy(tod, input); 387 return (0); 388 } 389