* Copyright (c) 1987 Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)ctime.c 5.14 (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */
return(asctime(localtime(t
)));
register struct tm
* timeptr
;
static char wday_name
[DAYS_PER_WEEK
][3] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
static char mon_name
[MONS_PER_YEAR
][3] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
(void) sprintf(result
, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
wday_name
[timeptr
->tm_wday
],
mon_name
[timeptr
->tm_mon
],
timeptr
->tm_mday
, timeptr
->tm_hour
,
timeptr
->tm_min
, timeptr
->tm_sec
,
TM_YEAR_BASE
+ timeptr
->tm_year
);
struct ttinfo
{ /* time type information */
long tt_gmtoff
; /* GMT offset in seconds */
int tt_isdst
; /* used to set tm_isdst */
int tt_abbrind
; /* abbreviation list index */
time_t ats
[TZ_MAX_TIMES
];
unsigned char types
[TZ_MAX_TIMES
];
struct ttinfo ttis
[TZ_MAX_TYPES
];
char chars
[TZ_MAX_CHARS
+ 1];
result
= (result
<< 8) | (codep
[i
] & 0xff);
if (name
== 0 && (name
= TZDEFAULT
) == 0)
char fullname
[MAXPATHLEN
];
doaccess
= name
[0] == '/';
if ((strlen(p
) + strlen(name
) + 1) >= sizeof fullname
)
(void) strcpy(fullname
, p
);
(void) strcat(fullname
, "/");
(void) strcat(fullname
, name
);
** Set doaccess if '.' (as in "../") shows up in name.
if (doaccess
&& access(name
, 4) != 0)
if ((fid
= open(name
, 0)) == -1)
register struct tzhead
* tzhp
;
i
= read(fid
, buf
, sizeof buf
);
if (close(fid
) != 0 || i
< sizeof *tzhp
)
tzhp
= (struct tzhead
*) buf
;
s
.timecnt
= (int) detzcode(tzhp
->tzh_timecnt
);
s
.typecnt
= (int) detzcode(tzhp
->tzh_typecnt
);
s
.charcnt
= (int) detzcode(tzhp
->tzh_charcnt
);
if (s
.timecnt
> TZ_MAX_TIMES
||
s
.typecnt
> TZ_MAX_TYPES
||
s
.charcnt
> TZ_MAX_CHARS
)
s
.timecnt
* (4 + sizeof (char)) +
s
.typecnt
* (4 + 2 * sizeof (char)) +
s
.charcnt
* sizeof (char))
for (i
= 0; i
< s
.timecnt
; ++i
) {
for (i
= 0; i
< s
.timecnt
; ++i
)
s
.types
[i
] = (unsigned char) *p
++;
for (i
= 0; i
< s
.typecnt
; ++i
) {
register struct ttinfo
* ttisp
;
ttisp
->tt_gmtoff
= detzcode(p
);
ttisp
->tt_isdst
= (unsigned char) *p
++;
ttisp
->tt_abbrind
= (unsigned char) *p
++;
for (i
= 0; i
< s
.charcnt
; ++i
)
s
.chars
[i
] = '\0'; /* ensure '\0' at end */
** Check that all the local time type indices are valid.
for (i
= 0; i
< s
.timecnt
; ++i
)
if (s
.types
[i
] >= s
.typecnt
)
** Check that all abbreviation indices are valid.
for (i
= 0; i
< s
.typecnt
; ++i
)
if (s
.ttis
[i
].tt_abbrind
>= s
.charcnt
)
** Set tzname elements to initial values.
tzname
[0] = tzname
[1] = &s
.chars
[0];
timezone
= -s
.ttis
[0].tt_gmtoff
;
for (i
= 1; i
< s
.typecnt
; ++i
) {
register struct ttinfo
* ttisp
;
tzname
[1] = &s
.chars
[ttisp
->tt_abbrind
];
tzname
[0] = &s
.chars
[ttisp
->tt_abbrind
];
timezone
= -ttisp
->tt_gmtoff
;
if (gettimeofday(&tv
, &tz
))
s
.timecnt
= 0; /* UNIX counts *west* of Greenwich */
s
.ttis
[0].tt_gmtoff
= tz
.tz_minuteswest
* -SECS_PER_MIN
;
s
.ttis
[0].tt_abbrind
= 0;
(void)strcpy(s
.chars
, _tztab(tz
.tz_minuteswest
, 0));
tzname
[0] = tzname
[1] = s
.chars
;
timezone
= tz
.tz_minuteswest
* 60;
daylight
= tz
.tz_dsttime
;
s
.ttis
[0].tt_abbrind
= 0;
(void) strcpy(s
.chars
, "GMT");
tzname
[0] = tzname
[1] = s
.chars
;
if (!name
|| *name
) { /* did not request GMT */
if (name
&& !tzload(name
)) /* requested name worked */
if (!tzload((char *)0)) /* default name worked */
if (!tzsetkernel()) /* kernel guess worked */
tzsetgmt(); /* GMT is default */
register struct ttinfo
* ttisp
;
register struct tm
* tmp
;
if (s
.timecnt
== 0 || t
< s
.ats
[0]) {
while (s
.ttis
[i
].tt_isdst
)
for (i
= 1; i
< s
.timecnt
; ++i
)
** To get (wrong) behavior that's compatible with System V Release 2.0
** you'd replace the statement below with
** tmp = offtime((time_t) (t + ttisp->tt_gmtoff), 0L);
tmp
= offtime(&t
, ttisp
->tt_gmtoff
);
tmp
->tm_isdst
= ttisp
->tt_isdst
;
tzname
[tmp
->tm_isdst
] = &s
.chars
[ttisp
->tt_abbrind
];
tmp
->tm_zone
= &s
.chars
[ttisp
->tt_abbrind
];
register struct tm
* tmp
;
tmp
= offtime(clock
, 0L);
tmp
->tm_zone
= "GMT"; /* UCT ? */
static int mon_lengths
[2][MONS_PER_YEAR
] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
static int year_lengths
[2] = {
DAYS_PER_NYEAR
, DAYS_PER_LYEAR
register struct tm
* tmp
;
days
= *clock
/ SECS_PER_DAY
;
rem
= *clock
% SECS_PER_DAY
;
while (rem
>= SECS_PER_DAY
) {
tmp
->tm_hour
= (int) (rem
/ SECS_PER_HOUR
);
rem
= rem
% SECS_PER_HOUR
;
tmp
->tm_min
= (int) (rem
/ SECS_PER_MIN
);
tmp
->tm_sec
= (int) (rem
% SECS_PER_MIN
);
tmp
->tm_wday
= (int) ((EPOCH_WDAY
+ days
) % DAYS_PER_WEEK
);
tmp
->tm_wday
+= DAYS_PER_WEEK
;
if (days
< (long) year_lengths
[yleap
])
days
= days
- (long) year_lengths
[yleap
];
days
= days
+ (long) year_lengths
[yleap
];
tmp
->tm_year
= y
- TM_YEAR_BASE
;
tmp
->tm_yday
= (int) days
;
for (tmp
->tm_mon
= 0; days
>= (long) ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
days
= days
- (long) ip
[tmp
->tm_mon
];
tmp
->tm_mday
= (int) (days
+ 1);