// XXX this is a little different - only invoked at login, // which we should update/calculate every variables to log. int pwcuLoginSave () { // XXX because LoginSave was called very long after // login_start_time, so we must reload passwd again // here to prevent race condition. // If you want to remove this reload, make sure // pwcuLoginSave is called AFTER login_start_time // was decided. int regdays = 0, prev_regdays = 0; int reftime = login_start_time; time4_t baseref = 0; struct tm baseref_tm = {0}; // XXX one more read here... can we avoid it? PWCU_START(); // new host from 'fromhost' strlcpy( u.lasthost, fromhost, sizeof( u.lasthost)); strlcpy(cuser.lasthost, fromhost, sizeof(cuser.lasthost)); // this must be valid. assert(login_start_time > 0); // adjust base reference by rounding to beginning of each day (0:00am) baseref = u.firstlogin; if (localtime4_r(&baseref, &baseref_tm)) { baseref_tm.tm_sec = baseref_tm.tm_min = baseref_tm.tm_hour = 0; baseref = mktime(&baseref_tm); } // invalid session? if (reftime < u.lastlogin) reftime = u.lastlogin; regdays = ( reftime - baseref) / DAY_SECONDS; prev_regdays = (u.lastlogin - baseref) / DAY_SECONDS; // assert(regdays >= prev_regdays); // plus one for initial day if ((int)u.numlogindays > prev_regdays+1) u.numlogindays = prev_regdays+1; // calculate numlogindays (only increase one per each key) if (regdays > prev_regdays) { ++u.numlogindays; is_first_login_of_today = 1; } cuser.numlogindays = u.numlogindays; // update last login time cuser.lastlogin = u.lastlogin = reftime; if (!PERM_HIDE(currutmp)) cuser.lastseen = u.lastseen = reftime; PWCU_END(); }
static void a_timestamp(char *buf, const time4_t *time) { struct tm pt; localtime4_r(time, &pt); sprintf(buf, "%02d/%02d/%02d", pt.tm_mon + 1, pt.tm_mday, (pt.tm_year + 1900) % 100); }
time4_t gettime(int line, time4_t dt, const char* head) { char yn[7]; struct tm ptime, endtime; time_t t; char prompt[STRLEN*2]; localtime4_r(&dt, &ptime); endtime = ptime; snprintf(yn, sizeof(yn), "%4d", ptime.tm_year + 1900); move(line, 0); SOLVE_ANSI_CACHE(); clrtoeol(); snprintf(prompt, sizeof(prompt), "%s 西元年:", head); do { getdata_buf(line, 0, prompt, yn, 5, NUMECHO); // signed: limited on (2037, ...) // unsigned: limited on (..., 1970) // let's restrict inside the boundary. } while ((endtime.tm_year = atoi(yn) - 1900) < 70 || endtime.tm_year > 135); strlcat(prompt, yn, sizeof(prompt)); strlcat(prompt, " 月:", sizeof(prompt)); snprintf(yn, sizeof(yn), "%d", ptime.tm_mon + 1); do { getdata_buf(line, 0, prompt, yn, 3, NUMECHO); } while ((endtime.tm_mon = atoi(yn) - 1) < 0 || endtime.tm_mon > 11); strlcat(prompt, yn, sizeof(prompt)); strlcat(prompt, " 日:", sizeof(prompt)); snprintf(yn, sizeof(yn), "%d", ptime.tm_mday); do { getdata_buf(line, 0, prompt, yn, 3, NUMECHO); } while ((endtime.tm_mday = atoi(yn)) < 1 || endtime.tm_mday > 31); snprintf(yn, sizeof(yn), "%d", ptime.tm_hour); strlcat(prompt, yn, sizeof(prompt)); strlcat(prompt, " 時(0-23):", sizeof(prompt)); do { getdata_buf(line, 0, prompt, yn, 3, NUMECHO); } while ((endtime.tm_hour = atoi(yn)) < 0 || endtime.tm_hour > 23); strlcat(prompt, yn, sizeof(prompt)); strlcat(prompt, " 分(0-59):", sizeof(prompt)); snprintf(yn, sizeof(yn), "%d", ptime.tm_min); do { getdata_buf(line, 0, prompt, yn, 3, NUMECHO); } while ((endtime.tm_min = atoi(yn)) < 0 || endtime.tm_min > 59); t = mktime(&endtime); /* saturation check */ if(t < 0) t = 1; if(t > INT_MAX) t = INT_MAX; return t; }
/* @param[in,out] fpath input as dirname, output as filename */ static inline int fhdr_stamp(char *fpath, fileheader_t *fh, int type) { char *ip = fpath; time4_t dtime = time(0); struct tm ptime; int res = 0; if (access(fpath, X_OK | R_OK | W_OK)) Mkdir(fpath); while (*(++ip)); *ip++ = '/'; switch (type) { case STAMP_FILE: do { sprintf(ip, "M.%d.A.%3.3X", (int)(++dtime), (unsigned int)(random() & 0xFFF)); } while ((res = OpenCreate(fpath, O_EXCL | O_WRONLY)) == -1 && errno == EEXIST); break; case STAMP_DIR: do { sprintf(ip, "D%X", (int)++dtime & 07777); } while ((res = Mkdir(fpath)) == -1 && errno == EEXIST); break; case STAMP_LINK: do { sprintf(ip, "S%X", (int)++dtime); } while ((res = symlink("temp", fpath)) == -1 && errno == EEXIST); break; default: // unknown return -1; break; } if (res == -1) return -1; if (type == STAMP_FILE) close(res); strlcpy(fh->filename, ip, sizeof(fh->filename)); localtime4_r(&dtime, &ptime); snprintf(fh->date, sizeof(fh->date), "%2d/%02d", ptime.tm_mon + 1, ptime.tm_mday); return 0; }
// XXX announce(man) directory uses a smaller range of file names. // TODO merge with common/bbs/fhdr_stamp.c int stampadir(char *fpath, fileheader_t * fh, int large_set) { register char *ip = fpath; time4_t dtime = COMMON_TIME; struct tm ptime; const int mask_small = 0xFFF, // basic (4096) mask_large = 0xFFFF; // large (65536) int mask = mask_small; int retries = 0; // try to create root path if (access(fpath, X_OK | R_OK | W_OK) != 0) Mkdir(fpath); // find tail while (*(++ip)); *ip++ = '/'; // loop to create file memset(fh, 0, sizeof(fileheader_t)); do { if (++retries > mask_small && mask == mask_small) { if (!large_set) return -1; mask = mask_large; } if (retries > mask_large) return -1; // create minimal length file name. sprintf(ip, "D%X", (int)++dtime & mask); } while (Mkdir(fpath) == -1); strlcpy(fh->filename, ip, sizeof(fh->filename)); localtime4_r(&dtime, &ptime); snprintf(fh->date, sizeof(fh->date), "%2d/%02d", ptime.tm_mon + 1, ptime.tm_mday); return 0; }