static void strftime_cmd (void) { /* Rather then using some sort of portable version of strftime, which would * miss the locale-specific features, just call the system routine. However, * it cannot be called blindly because some versions (e.g., the the one from * c.snippets.org) do no input checking, and use code such as * * static char *day[] = {"Sunday", "Monday", ..., "Saturday"}; * [...] * switch (*f++) * { * case 'A' : * r = day[t->tm_wday]; * break; * [...] * * and lead to a SEGV if t->tm_wday is not in the range [0:6]. */ struct tm tms; char buf[4096]; int status; char *fmt; if (SLang_Num_Function_Args == 1) { time_t t = time(NULL); if (-1 == call_localtime (t, &tms)) return; if (-1 == validate_tm (&tms)) return; } else if (-1 == pop_tm_struct (&tms)) return; if (-1 == SLang_pop_slstring (&fmt)) return; /* Ugh. The man page says: * * The strftime() function returns the number of characters placed in the * array s, not including the terminating NUL character, provided the * string, including the terminating NUL, fits. Otherwise, it returns 0, * and the contents of the array is undefined. (Thus at least since libc * 4.4.4; very old versions of libc, such as libc 4.4.1, would return max * if the array was too small.) * * Note that the return value 0 does not necessarily indicate an error; * for example, in many locales %p yields an empty string. * * Was this too designed by committee? */ status = strftime (buf, sizeof(buf), fmt, &tms); if (status == 0) buf[0] = 0; buf[sizeof(buf)-1] = 0; (void) SLang_push_string (buf); SLang_free_slstring (fmt); }
static int pop_tm_struct (struct tm *tms) { /* The memset is necessary because GLIBC has extra fields that may be * meaningful. In fact, without it strftime will generate access errors */ memset ((char *) tms, 0, sizeof (*tms)); if (-1 == SLang_pop_cstruct (tms, TM_Struct)) return -1; return validate_tm (tms); }
/**************************************************************** * RD_Cnv_tm_to_DTString * Copies tm struct values into a date string. Returns * size_t length copied. Returns 0 if invalid tm struct. *****************************************************************/ size_t RD_Cnv_tm_to_DTString(struct tm *tmptr,char * dest) { char theyear[5]; char themonth[3]; char theday[3]; char thehr[3]; char themin[3]; char thesec[3]; char plusminus[3]; char minus[2] = "-"; char colon_sep[4] = ":"; char T_sep[2] = "T"; char offsethr[3]; char offsetmin[3]; double offsetfromutc; int offhr = 0; int offmin = 0; int val; int leap = 0; if (!validate_tm(tmptr)) { dest[0]=0; return 0; } offsetfromutc = get_local_offset(); if (offsetfromutc > 0) strlcpy(plusminus,"%2b",3); else strlcpy(plusminus,"-",1); offhr = (int) (offsetfromutc / 3600); double hold_min; double divby = 3600; hold_min = fmod(offsetfromutc,divby); offmin = (int) (hold_min / 60); sprintf(offsethr,"%02d",abs(offhr)); sprintf(offsetmin,"%02d",abs(offmin)); val = tmptr->tm_year + 1900; sprintf(theyear,"%d",val); val = tmptr->tm_mon + 1; sprintf(themonth,"%02d",val); sprintf(theday,"%02d",tmptr->tm_mday); sprintf(thehr,"%02d",tmptr->tm_hour); sprintf(themin,"%02d",tmptr->tm_min); sprintf(thesec,"%02d",tmptr->tm_sec); strlcpy(dest,theyear,4); strcat(dest, minus); strcat(dest,themonth); strcat(dest, minus); strcat(dest,theday); strcat(dest,T_sep); strcat(dest,thehr); strcat(dest,colon_sep); strcat(dest,themin); strcat(dest,colon_sep); strcat(dest,thesec); strcat(dest,plusminus); strcat(dest,offsethr); strcat(dest,colon_sep); strcat(dest,offsetmin); return strlen(dest); }