157196Smuller /*- 257196Smuller * Copyright (c) 1992 Keith Muller. 357196Smuller * Copyright (c) 1992 The Regents of the University of California. 457196Smuller * All rights reserved. 557196Smuller * 657196Smuller * This code is derived from software contributed to Berkeley by 757196Smuller * Keith Muller of the University of California, San Diego. 857196Smuller * 957196Smuller * %sccs.include.redist.c% 1057196Smuller */ 1157196Smuller 1257196Smuller #ifndef lint 13*57501Smuller static char sccsid[] = "@(#)sel_subs.c 1.2 (Berkeley) 01/12/93"; 1457196Smuller #endif /* not lint */ 1557196Smuller 1657196Smuller #include <sys/types.h> 1757196Smuller #include <sys/time.h> 1857196Smuller #include <sys/stat.h> 1957196Smuller #include <sys/param.h> 2057196Smuller #include <pwd.h> 2157196Smuller #include <grp.h> 2257196Smuller #include <stdio.h> 2357196Smuller #include <ctype.h> 2457196Smuller #include <string.h> 2557196Smuller #include <strings.h> 2657196Smuller #include <unistd.h> 2757196Smuller #include <stdlib.h> 2857196Smuller #include "pax.h" 2957196Smuller #include "sel_subs.h" 3057196Smuller #include "extern.h" 3157196Smuller 3257196Smuller static int str_sec __P((register char *, time_t *)); 3357196Smuller static int usr_match __P((register ARCHD *)); 3457196Smuller static int grp_match __P((register ARCHD *)); 3557196Smuller static int trng_match __P((register ARCHD *)); 3657196Smuller 3757196Smuller static TIME_RNG *trhead = NULL; /* time range list head */ 3857196Smuller static TIME_RNG *trtail = NULL; /* time range list tail */ 3957196Smuller static USRT **usrtb = NULL; /* user selection table */ 4057196Smuller static GRPT **grptb = NULL; /* group selection table */ 4157196Smuller 4257196Smuller /* 4357196Smuller * Routines for selection of archive members 4457196Smuller */ 4557196Smuller 4657196Smuller /* 4757196Smuller * sel_chk() 48*57501Smuller * check if this file matches a specfied uid, gid or time range 4957196Smuller * Return: 5057196Smuller * 0 if this archive member should be processed, 1 if it should be skipped 5157196Smuller */ 5257196Smuller 5357196Smuller #if __STDC__ 5457196Smuller int 5557196Smuller sel_chk(register ARCHD *arcn) 5657196Smuller #else 5757196Smuller int 5857196Smuller sel_chk(arcn) 5957196Smuller register ARCHD *arcn; 6057196Smuller #endif 6157196Smuller { 6257196Smuller if (((usrtb != NULL) && usr_match(arcn)) || 6357196Smuller ((grptb != NULL) && grp_match(arcn)) || 6457196Smuller ((trhead != NULL) && trng_match(arcn))) 6557196Smuller return(1); 6657196Smuller return(0); 6757196Smuller } 6857196Smuller 6957196Smuller /* 7057196Smuller * User/group selection routines 7157196Smuller * 72*57501Smuller * Routines to handle user selection of files based on the file uid/gid. To 73*57501Smuller * add an entry, the user supplies either then name or the uid/gid starting with 74*57501Smuller * a # on the command line. A \# will eascape the #. 7557196Smuller */ 7657196Smuller 7757196Smuller /* 7857196Smuller * usr_add() 7957196Smuller * add a user match to the user match hash table 8057196Smuller * Return: 8157196Smuller * 0 if added ok, -1 otherwise; 8257196Smuller */ 8357196Smuller 8457196Smuller #if __STDC__ 8557196Smuller int 8657196Smuller usr_add(register char *str) 8757196Smuller #else 8857196Smuller int 8957196Smuller usr_add(str) 9057196Smuller register char *str; 9157196Smuller #endif 9257196Smuller { 9357196Smuller register u_int indx; 9457196Smuller register USRT *pt; 9557196Smuller register struct passwd *pw; 9657196Smuller register uid_t uid; 9757196Smuller 9857196Smuller /* 9957196Smuller * create the table if it doesn't exist 10057196Smuller */ 10157196Smuller if ((str == NULL) || (*str == '\0')) 10257196Smuller return(-1); 10357196Smuller if ((usrtb == NULL) && 10457196Smuller ((usrtb = (USRT **)calloc(USR_TB_SZ, sizeof(USRT *))) == NULL)) { 10557196Smuller warn(1, "Unable to allocate memory for user selection table"); 10657196Smuller return(-1); 10757196Smuller } 10857196Smuller 10957196Smuller /* 11057196Smuller * figure out user spec 11157196Smuller */ 11257196Smuller if (str[0] != '#') { 11357196Smuller /* 11457196Smuller * it is a user name, \# escapes # as first char in user name 11557196Smuller */ 11657196Smuller if ((str[0] == '\\') && (str[1] == '#')) 11757196Smuller ++str; 11857196Smuller if ((pw = getpwnam(str)) == NULL) { 11957196Smuller warn(1, "Unable to find uid for user: %s", str); 12057196Smuller return(-1); 12157196Smuller } 12257196Smuller uid = (uid_t)pw->pw_uid; 12357196Smuller } else 12457196Smuller # ifdef NET2_STAT 12557196Smuller uid = (uid_t)atoi(str+1); 12657196Smuller # else 12757196Smuller uid = (uid_t)strtoul(str+1, (char **)NULL, 10); 12857196Smuller # endif 12957196Smuller endpwent(); 13057196Smuller 13157196Smuller /* 13257196Smuller * hash it and go down the hash chain (if any) looking for it 13357196Smuller */ 13457196Smuller indx = ((unsigned)uid) % USR_TB_SZ; 13557196Smuller if ((pt = usrtb[indx]) != NULL) { 13657196Smuller while (pt != NULL) { 13757196Smuller if (pt->uid == uid) 13857196Smuller return(0); 13957196Smuller pt = pt->fow; 14057196Smuller } 14157196Smuller } 14257196Smuller 14357196Smuller /* 144*57501Smuller * uid is not yet in the table, add it to the front of the chain 14557196Smuller */ 14657196Smuller if ((pt = (USRT *)malloc(sizeof(USRT))) != NULL) { 14757196Smuller pt->uid = uid; 14857196Smuller pt->fow = usrtb[indx]; 14957196Smuller usrtb[indx] = pt; 15057196Smuller return(0); 15157196Smuller } 15257196Smuller warn(1, "User selection table out of memory"); 15357196Smuller return(-1); 15457196Smuller } 15557196Smuller 15657196Smuller /* 15757196Smuller * usr_match() 15857196Smuller * check if this files uid matches a selected uid. 15957196Smuller * Return: 16057196Smuller * 0 if this archive member should be processed, 1 if it should be skipped 16157196Smuller */ 16257196Smuller 16357196Smuller #if __STDC__ 16457196Smuller static int 16557196Smuller usr_match(register ARCHD *arcn) 16657196Smuller #else 16757196Smuller static int 16857196Smuller usr_match(arcn) 16957196Smuller register ARCHD *arcn; 17057196Smuller #endif 17157196Smuller { 17257196Smuller register USRT *pt; 17357196Smuller 17457196Smuller /* 17557196Smuller * hash and look for it in the table 17657196Smuller */ 17757196Smuller pt = usrtb[((unsigned)arcn->sb.st_uid) % USR_TB_SZ]; 17857196Smuller while (pt != NULL) { 17957196Smuller if (pt->uid == arcn->sb.st_uid) 18057196Smuller return(0); 18157196Smuller pt = pt->fow; 18257196Smuller } 18357196Smuller 18457196Smuller /* 18557196Smuller * not found 18657196Smuller */ 18757196Smuller return(1); 18857196Smuller } 18957196Smuller 19057196Smuller /* 19157196Smuller * grp_add() 19257196Smuller * add a group match to the group match hash table 19357196Smuller * Return: 19457196Smuller * 0 if added ok, -1 otherwise; 19557196Smuller */ 19657196Smuller 19757196Smuller #if __STDC__ 19857196Smuller int 19957196Smuller grp_add(register char *str) 20057196Smuller #else 20157196Smuller int 20257196Smuller grp_add(str) 20357196Smuller register char *str; 20457196Smuller #endif 20557196Smuller { 20657196Smuller register u_int indx; 20757196Smuller register GRPT *pt; 20857196Smuller register struct group *gr; 20957196Smuller register gid_t gid; 21057196Smuller 21157196Smuller /* 21257196Smuller * create the table if it doesn't exist 21357196Smuller */ 21457196Smuller if ((str == NULL) || (*str == '\0')) 21557196Smuller return(-1); 21657196Smuller if ((grptb == NULL) && 21757196Smuller ((grptb = (GRPT **)calloc(GRP_TB_SZ, sizeof(GRPT *))) == NULL)) { 21857196Smuller warn(1, "Unable to allocate memory fo group selection table"); 21957196Smuller return(-1); 22057196Smuller } 22157196Smuller 22257196Smuller /* 22357196Smuller * figure out user spec 22457196Smuller */ 22557196Smuller if (str[0] != '#') { 22657196Smuller /* 22757196Smuller * it is a group name, \# escapes # as first char in group name 22857196Smuller */ 22957196Smuller if ((str[0] == '\\') && (str[1] == '#')) 23057196Smuller ++str; 23157196Smuller if ((gr = getgrnam(str)) == NULL) { 23257196Smuller warn(1,"Cannot determine gid for group name: %s", str); 23357196Smuller return(-1); 23457196Smuller } 23557196Smuller gid = (gid_t)gr->gr_gid; 23657196Smuller } else 23757196Smuller # ifdef NET2_STAT 23857196Smuller gid = (gid_t)atoi(str+1); 23957196Smuller # else 24057196Smuller gid = (gid_t)strtoul(str+1, (char **)NULL, 10); 24157196Smuller # endif 24257196Smuller endgrent(); 24357196Smuller 24457196Smuller /* 24557196Smuller * hash it and go down the hash chain (if any) looking for it 24657196Smuller */ 24757196Smuller indx = ((unsigned)gid) % GRP_TB_SZ; 24857196Smuller if ((pt = grptb[indx]) != NULL) { 24957196Smuller while (pt != NULL) { 25057196Smuller if (pt->gid == gid) 25157196Smuller return(0); 25257196Smuller pt = pt->fow; 25357196Smuller } 25457196Smuller } 25557196Smuller 25657196Smuller /* 257*57501Smuller * gid not in the table, add it to the front of the chain 25857196Smuller */ 25957196Smuller if ((pt = (GRPT *)malloc(sizeof(GRPT))) != NULL) { 26057196Smuller pt->gid = gid; 26157196Smuller pt->fow = grptb[indx]; 26257196Smuller grptb[indx] = pt; 26357196Smuller return(0); 26457196Smuller } 26557196Smuller warn(1, "Group selection table out of memory"); 26657196Smuller return(-1); 26757196Smuller } 26857196Smuller 26957196Smuller /* 27057196Smuller * grp_match() 27157196Smuller * check if this files gid matches a selected gid. 27257196Smuller * Return: 27357196Smuller * 0 if this archive member should be processed, 1 if it should be skipped 27457196Smuller */ 27557196Smuller 27657196Smuller #if __STDC__ 27757196Smuller static int 27857196Smuller grp_match(register ARCHD *arcn) 27957196Smuller #else 28057196Smuller static int 28157196Smuller grp_match(arcn) 28257196Smuller register ARCHD *arcn; 28357196Smuller #endif 28457196Smuller { 28557196Smuller register GRPT *pt; 28657196Smuller 28757196Smuller /* 28857196Smuller * hash and look for it in the table 28957196Smuller */ 29057196Smuller pt = grptb[((unsigned)arcn->sb.st_gid) % GRP_TB_SZ]; 29157196Smuller while (pt != NULL) { 29257196Smuller if (pt->gid == arcn->sb.st_gid) 29357196Smuller return(0); 29457196Smuller pt = pt->fow; 29557196Smuller } 29657196Smuller 29757196Smuller /* 29857196Smuller * not found 29957196Smuller */ 30057196Smuller return(1); 30157196Smuller } 30257196Smuller 30357196Smuller /* 30457196Smuller * Time range selection routines 30557196Smuller * 306*57501Smuller * Routines to handle user selection of files based on the modification and/or 307*57501Smuller * inode change time falling within a specified time range (the non-standard 308*57501Smuller * -T flag). The user may specify any number of different file time ranges. 309*57501Smuller * Time ranges are checked one at a time until a match is found (if at all). 310*57501Smuller * If the file has a mtime (and/or ctime) which lies within one of the time 311*57501Smuller * ranges, the file is selected. Time ranges may have a lower and/or a upper 312*57501Smuller * value. These ranges are inclusive. When no time ranges are supplied to pax 313*57501Smuller * with the -T option, all members in the archive will be selected by the time 314*57501Smuller * range routines. When only a lower range is supplied, only files with a 315*57501Smuller * mtime (and/or ctime) equal to or younger are selected. When only a upper 316*57501Smuller * range is supplied, only files with a mtime (and/or ctime) equal to or older 317*57501Smuller * are selected. When the lower time range is equal to the upper time range, 318*57501Smuller * only files with a mtime (or ctime) of exactly that time are selected. 31957196Smuller */ 32057196Smuller 32157196Smuller /* 32257196Smuller * trng_add() 32357196Smuller * add a time range match to the time range list. 32457196Smuller * This is a non-standard pax option. Lower and upper ranges are in the 32557196Smuller * format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated. 32657196Smuller * Time ranges are based on current time, so 1234 would specify a time of 32757196Smuller * 12:34 today. 32857196Smuller * Return: 32957196Smuller * 0 if the time range was added to the list, -1 otherwise 33057196Smuller */ 33157196Smuller 33257196Smuller #if __STDC__ 33357196Smuller int 33457196Smuller trng_add(register char *str) 33557196Smuller #else 33657196Smuller int 33757196Smuller trng_add(str) 33857196Smuller register char *str; 33957196Smuller #endif 34057196Smuller { 34157196Smuller register TIME_RNG *pt; 34257196Smuller register char *up_pt = NULL; 34357196Smuller register char *stpt; 344*57501Smuller register char *flgpt; 34557196Smuller register int dot = 0; 34657196Smuller 34757196Smuller /* 34857196Smuller * throw out the badly formed time ranges 34957196Smuller */ 35057196Smuller if ((str == NULL) || (*str == '\0')) { 35157196Smuller warn(1, "Empty time range string"); 35257196Smuller return(-1); 35357196Smuller } 35457196Smuller 355*57501Smuller /* 356*57501Smuller * locate optional flags suffix /{cm}. We only allow a flag suffix(s) 357*57501Smuller * in write and copy (as none of the formats stores inode change time; 358*57501Smuller * currently inode change time cannot be set to a specific value by 359*57501Smuller * any system call). 360*57501Smuller */ 361*57501Smuller if ((flgpt = rindex(str, '/')) != NULL) { 362*57501Smuller *flgpt++ = '\0'; 363*57501Smuller if ((act == LIST) || (act == EXTRACT)) { 364*57501Smuller warn(1,"Time suffix only valid in write or copy modes"); 365*57501Smuller return(-1); 366*57501Smuller } 367*57501Smuller } 368*57501Smuller 36957196Smuller for (stpt = str; *stpt != '\0'; ++stpt) { 37057196Smuller if ((*stpt >= '0') && (*stpt <= '9')) 37157196Smuller continue; 37257196Smuller if ((*stpt == ',') && (up_pt == NULL)) { 37357196Smuller *stpt = '\0'; 37457196Smuller up_pt = stpt + 1; 37557196Smuller dot = 0; 37657196Smuller continue; 37757196Smuller } 37857196Smuller 37957196Smuller /* 38057196Smuller * allow only one dot per range (secs) 38157196Smuller */ 38257196Smuller if ((*stpt == '.') && (!dot)) { 38357196Smuller ++dot; 38457196Smuller continue; 38557196Smuller } 38657196Smuller warn(1, "Improperly specified time range: %s", str); 38757196Smuller goto out; 38857196Smuller } 38957196Smuller 39057196Smuller /* 39157196Smuller * allocate space for the time range and store the limits 39257196Smuller */ 39357196Smuller if ((pt = (TIME_RNG *)malloc(sizeof(TIME_RNG))) == NULL) { 39457196Smuller warn(1, "Unable to allocate memory for time range"); 39557196Smuller return(-1); 39657196Smuller } 39757196Smuller 39857196Smuller /* 399*57501Smuller * by default we only will check file mtime, but usee can specify 400*57501Smuller * mtime, ctime (inode change time) or both. 401*57501Smuller */ 402*57501Smuller if ((flgpt == NULL) || (*flgpt == '\0')) 403*57501Smuller pt->flgs = CMPMTME; 404*57501Smuller else { 405*57501Smuller pt->flgs = 0; 406*57501Smuller while (*flgpt != '\0') { 407*57501Smuller switch(*flgpt) { 408*57501Smuller case 'M': 409*57501Smuller case 'm': 410*57501Smuller pt->flgs |= CMPMTME; 411*57501Smuller break; 412*57501Smuller case 'C': 413*57501Smuller case 'c': 414*57501Smuller pt->flgs |= CMPCTME; 415*57501Smuller break; 416*57501Smuller default: 417*57501Smuller warn(1, "Bad option %c with time range %s", 418*57501Smuller *flgpt, str); 419*57501Smuller goto out; 420*57501Smuller } 421*57501Smuller ++flgpt; 422*57501Smuller } 423*57501Smuller } 424*57501Smuller 425*57501Smuller /* 42657196Smuller * start off with the current time 42757196Smuller */ 42857196Smuller pt->low_time = pt->high_time = time((time_t *)NULL); 42957196Smuller if (*str != '\0') { 43057196Smuller /* 43157196Smuller * add lower limit 43257196Smuller */ 43357196Smuller if (str_sec(str, &(pt->low_time)) < 0) { 43457196Smuller warn(1, "Illegal lower time range %s", str); 43557196Smuller (void)free((char *)pt); 43657196Smuller goto out; 43757196Smuller } 438*57501Smuller pt->flgs |= HASLOW; 43957196Smuller } 44057196Smuller 44157196Smuller if ((up_pt != NULL) && (*up_pt != '\0')) { 44257196Smuller /* 44357196Smuller * add upper limit 44457196Smuller */ 44557196Smuller if (str_sec(up_pt, &(pt->high_time)) < 0) { 44657196Smuller warn(1, "Illegal upper time range %s", up_pt); 44757196Smuller (void)free((char *)pt); 44857196Smuller goto out; 44957196Smuller } 450*57501Smuller pt->flgs |= HASHIGH; 45157196Smuller 45257196Smuller /* 45357196Smuller * check that the upper and lower do not overlap 45457196Smuller */ 455*57501Smuller if (pt->flgs & HASLOW) { 45657196Smuller if (pt->low_time > pt->high_time) { 45757196Smuller warn(1, "Upper %s and lower %s time overlap", 45857196Smuller up_pt, str); 45957196Smuller (void)free((char *)pt); 46057196Smuller return(-1); 46157196Smuller } 46257196Smuller } 46357196Smuller } 46457196Smuller 46557196Smuller pt->fow = NULL; 46657196Smuller if (trhead == NULL) { 46757196Smuller trtail = trhead = pt; 46857196Smuller return(0); 46957196Smuller } 47057196Smuller trtail->fow = pt; 47157196Smuller trtail = pt; 47257196Smuller return(0); 473*57501Smuller 47457196Smuller out: 475*57501Smuller warn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]"); 47657196Smuller return(-1); 47757196Smuller } 47857196Smuller 47957196Smuller /* 48057196Smuller * trng_match() 481*57501Smuller * check if this files mtime/ctime falls within any supplied time range. 48257196Smuller * Return: 48357196Smuller * 0 if this archive member should be processed, 1 if it should be skipped 48457196Smuller */ 48557196Smuller 48657196Smuller #if __STDC__ 48757196Smuller static int 48857196Smuller trng_match(register ARCHD *arcn) 48957196Smuller #else 49057196Smuller static int 49157196Smuller trng_match(arcn) 49257196Smuller register ARCHD *arcn; 49357196Smuller #endif 49457196Smuller { 49557196Smuller register TIME_RNG *pt; 49657196Smuller 49757196Smuller /* 49857196Smuller * have to search down the list one at a time looking for a match. 49957196Smuller * remember time range limits are inclusive. 50057196Smuller */ 50157196Smuller pt = trhead; 50257196Smuller while (pt != NULL) { 503*57501Smuller switch(pt->flgs & CMPBOTH) { 504*57501Smuller case CMPBOTH: 505*57501Smuller /* 506*57501Smuller * user wants both mtime and ctime checked for this 507*57501Smuller * time range 508*57501Smuller */ 509*57501Smuller if (((pt->flgs & HASLOW) && 510*57501Smuller (arcn->sb.st_mtime < pt->low_time) && 511*57501Smuller (arcn->sb.st_ctime < pt->low_time)) || 512*57501Smuller ((pt->flgs & HASHIGH) && 513*57501Smuller (arcn->sb.st_mtime > pt->high_time) && 514*57501Smuller (arcn->sb.st_ctime > pt->high_time))) { 51557196Smuller pt = pt->fow; 51657196Smuller continue; 51757196Smuller } 518*57501Smuller break; 519*57501Smuller case CMPCTME: 520*57501Smuller /* 521*57501Smuller * user wants only ctime checked for this time range 522*57501Smuller */ 523*57501Smuller if (((pt->flgs & HASLOW) && 524*57501Smuller (arcn->sb.st_ctime < pt->low_time)) || 525*57501Smuller ((pt->flgs & HASHIGH) && 526*57501Smuller (arcn->sb.st_ctime > pt->high_time))) { 52757196Smuller pt = pt->fow; 52857196Smuller continue; 52957196Smuller } 530*57501Smuller break; 531*57501Smuller case CMPMTME: 532*57501Smuller default: 533*57501Smuller /* 534*57501Smuller * user wants only mtime checked for this time range 535*57501Smuller */ 536*57501Smuller if (((pt->flgs & HASLOW) && 537*57501Smuller (arcn->sb.st_mtime < pt->low_time)) || 538*57501Smuller ((pt->flgs & HASHIGH) && 539*57501Smuller (arcn->sb.st_mtime > pt->high_time))) { 540*57501Smuller pt = pt->fow; 541*57501Smuller continue; 542*57501Smuller } 543*57501Smuller break; 54457196Smuller } 54557196Smuller break; 54657196Smuller } 54757196Smuller 54857196Smuller if (pt == NULL) 54957196Smuller return(1); 55057196Smuller return(0); 55157196Smuller } 55257196Smuller 55357196Smuller /* 55457196Smuller * str_sec() 55557196Smuller * Convert a time string in the format of [yy[mm[dd[hh]]]]mm[.ss] to gmt 55657196Smuller * seconds. Tval already has current time loaded into it at entry. 55757196Smuller * Return: 55857196Smuller * 0 if converted ok, -1 otherwise 55957196Smuller */ 56057196Smuller 56157196Smuller #if __STDC__ 56257196Smuller static int 56357196Smuller str_sec(register char *str, time_t *tval) 56457196Smuller #else 56557196Smuller static int 56657196Smuller str_sec(str, tval) 56757196Smuller register char *str; 56857196Smuller time_t *tval; 56957196Smuller #endif 57057196Smuller { 57157196Smuller register struct tm *lt; 57257196Smuller register char *dot = NULL; 57357196Smuller 57457196Smuller lt = localtime(tval); 57557196Smuller if ((dot = index(str, '.')) != NULL) { 57657196Smuller /* 57757196Smuller * seconds (.ss) 57857196Smuller */ 57957196Smuller *dot++ = '\0'; 58057196Smuller if (strlen(dot) != 2) 58157196Smuller return(-1); 58257196Smuller if ((lt->tm_sec = ATOI2(dot)) > 61) 58357196Smuller return(-1); 58457196Smuller } else 58557196Smuller lt->tm_sec = 0; 58657196Smuller 58757196Smuller switch (strlen(str)) { 58857196Smuller case 10: 58957196Smuller /* 59057196Smuller * year (yy) 59157196Smuller * watch out for year 2000 59257196Smuller */ 59357196Smuller if ((lt->tm_year = ATOI2(str)) < 69) 59457196Smuller lt->tm_year += 100; 59557196Smuller str += 2; 59657196Smuller /* FALLTHROUGH */ 59757196Smuller case 8: 59857196Smuller /* 59957196Smuller * month (mm) 60057196Smuller * watch out months are from 0 - 11 internally 60157196Smuller */ 60257196Smuller if ((lt->tm_mon = ATOI2(str)) > 12) 60357196Smuller return(-1); 60457196Smuller --lt->tm_mon; 60557196Smuller str += 2; 60657196Smuller /* FALLTHROUGH */ 60757196Smuller case 6: 60857196Smuller /* 60957196Smuller * day (dd) 61057196Smuller */ 61157196Smuller if ((lt->tm_mday = ATOI2(str)) > 31) 61257196Smuller return(-1); 61357196Smuller str += 2; 61457196Smuller /* FALLTHROUGH */ 61557196Smuller case 4: 61657196Smuller /* 61757196Smuller * hour (hh) 61857196Smuller */ 61957196Smuller if ((lt->tm_hour = ATOI2(str)) > 23) 62057196Smuller return(-1); 62157196Smuller str += 2; 62257196Smuller /* FALLTHROUGH */ 62357196Smuller case 2: 62457196Smuller /* 62557196Smuller * minute (mm) 62657196Smuller */ 62757196Smuller if ((lt->tm_min = ATOI2(str)) > 59) 62857196Smuller return(-1); 62957196Smuller break; 63057196Smuller default: 63157196Smuller return(-1); 63257196Smuller } 63357196Smuller /* 63457196Smuller * convert broken-down time to GMT clock time seconds 63557196Smuller */ 63657196Smuller if ((*tval = mktime(lt)) == -1) 63757196Smuller return(-1); 63857196Smuller return(0); 63957196Smuller } 640