home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / 3b1 / volume02 / libbsd / part02 < prev    next >
Encoding:
Internet Message Format  |  1992-06-22  |  54.7 KB

  1. Path: comp-sources-3b1
  2. From: dave@galaxia.newport.ri.us (David H. Brierley)
  3. Subject:  v02i005:  BSD Compatibility Library for ATT 3B1, Part02/02
  4. Newsgroups: comp.sources.3b1
  5. Approved: dave@galaxia.newport.ri.us
  6. X-Checksum-Snefru: eebb21bf 36a64c66 0221e8cc a4a16822
  7.  
  8. Submitted-by: dave@galaxia.newport.ri.us (David H. Brierley)
  9. Posting-number: Volume 2, Issue 5
  10. Archive-name: libbsd/part02
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 2 (of 2)."
  19. # Contents:  getdate.y mkdir.c random.c strftime.3 strftime.c
  20. # Wrapped by dave@galaxia on Sat Jun 13 15:23:54 1992
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'getdate.y' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'getdate.y'\"
  24. else
  25. echo shar: Extracting \"'getdate.y'\" \(20818 characters\)
  26. sed "s/^X//" >'getdate.y' <<'END_OF_FILE'
  27. X%{
  28. X/* $Revision: 2.1 $
  29. X**
  30. X**  Originally written by Steven M. Bellovin <smb@research.att.com> while
  31. X**  at the University of North Carolina at Chapel Hill.  Later tweaked by
  32. X**  a couple of people on Usenet.  Completely overhauled by Rich $alz
  33. X**  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
  34. X**  send any email to Rich.
  35. X**
  36. X**  This grammar has eight shift/reduce conflicts.
  37. X**
  38. X**  This code is in the public domain and has no copyright.
  39. X*/
  40. X/* SUPPRESS 287 on yaccpar_sccsid *//* Unusd static variable */
  41. X/* SUPPRESS 288 on yyerrlab *//* Label unused */
  42. X#include "defs.h"
  43. X#include <stdio.h>
  44. X#include <ctype.h>
  45. X
  46. X#if    defined(vms)
  47. X#include <types.h>
  48. X#include <time.h>
  49. X#else
  50. X#include <sys/types.h>
  51. X#if    defined(USG)
  52. X/*
  53. X**  Uncomment the next line if you need to do a tzset() call to set the
  54. X**  timezone, and don't have ftime().  Some SystemV releases, I think.
  55. X*/
  56. X#define NEED_TZSET
  57. Xstruct timeb {
  58. X    time_t        time;        /* Seconds since the epoch    */
  59. X    unsigned short    millitm;    /* Field not used        */
  60. X    short        timezone;
  61. X    short        dstflag;    /* Field not used        */
  62. X};
  63. X#else
  64. X#include <sys/timeb.h>
  65. X#endif    /* defined(USG) */
  66. X#if    defined(BSD4_2)
  67. X#include <sys/time.h>
  68. X#else
  69. X#include <time.h>
  70. X#endif    /* defined(BSD4_2) */
  71. X#endif    /* defined(vms) */
  72. X
  73. X#if    !defined(lint) && !defined(SABER)
  74. Xstatic char RCS[] =
  75. X    "$Header: str2date.y,v 2.1 90/09/06 08:15:06 cronan Exp $";
  76. X#endif    /* !defined(lint) && !defined(SABER) */
  77. X
  78. X
  79. X#define EPOCH        1970
  80. X#define HOUR(x)        (x * 60)
  81. X#define SECSPERDAY    (24L * 60L * 60L)
  82. X
  83. X
  84. X/*
  85. X**  An entry in the lexical lookup table.
  86. X*/
  87. Xtypedef struct _TABLE {
  88. X    char    *name;
  89. X    int        type;
  90. X    time_t    value;
  91. X} TABLE;
  92. X
  93. X
  94. X/*
  95. X**  Daylight-savings mode:  on, off, or not yet known.
  96. X*/
  97. Xtypedef enum _DSTMODE {
  98. X    DSTon, DSToff, DSTmaybe
  99. X} DSTMODE;
  100. X
  101. X/*
  102. X**  Meridian:  am, pm, or 24-hour style.
  103. X*/
  104. Xtypedef enum _MERIDIAN {
  105. X    MERam, MERpm, MER24
  106. X} MERIDIAN;
  107. X
  108. X
  109. X/*
  110. X**  Global variables.  We could get rid of most of these by using a good
  111. X**  union as the yacc stack.  (This routine was originally written before
  112. X**  yacc had the %union construct.)  Maybe someday; right now we only use
  113. X**  the %union very rarely.
  114. X*/
  115. Xstatic char    *yyInput;
  116. Xstatic DSTMODE    yyDSTmode;
  117. Xstatic time_t    yyDayOrdinal;
  118. Xstatic time_t    yyDayNumber;
  119. Xstatic int    yyHaveDate;
  120. Xstatic int    yyHaveDay;
  121. Xstatic int    yyHaveRel;
  122. Xstatic int    yyHaveTime;
  123. Xstatic int    yyHaveZone;
  124. Xstatic time_t    yyTimezone;
  125. Xstatic time_t    yyDay;
  126. Xstatic time_t    yyHour;
  127. Xstatic time_t    yyMinutes;
  128. Xstatic time_t    yyMonth;
  129. Xstatic time_t    yySeconds;
  130. Xstatic time_t    yyYear;
  131. Xstatic MERIDIAN    yyMeridian;
  132. Xstatic time_t    yyRelMonth;
  133. Xstatic time_t    yyRelSeconds;
  134. X
  135. X
  136. Xextern struct tm    *localtime();
  137. X%}
  138. X
  139. X%union {
  140. X    time_t        Number;
  141. X    enum _MERIDIAN    Meridian;
  142. X}
  143. X
  144. X%token    tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
  145. X%token    tSEC_UNIT tSNUMBER tUNUMBER tZONE
  146. X
  147. X%type    <Number>    tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
  148. X%type    <Number>    tSEC_UNIT tSNUMBER tUNUMBER tZONE
  149. X%type    <Meridian>    tMERIDIAN o_merid
  150. X
  151. X%%
  152. X
  153. Xspec    : /* NULL */
  154. X    | spec item
  155. X    ;
  156. X
  157. Xitem    : time {
  158. X        yyHaveTime++;
  159. X    }
  160. X    | zone {
  161. X        yyHaveZone++;
  162. X    }
  163. X    | date {
  164. X        yyHaveDate++;
  165. X    }
  166. X    | day {
  167. X        yyHaveDay++;
  168. X    }
  169. X    | rel {
  170. X        yyHaveRel++;
  171. X    }
  172. X    | number
  173. X    ;
  174. X
  175. Xtime    : tUNUMBER tMERIDIAN {
  176. X        yyHour = $1;
  177. X        yyMinutes = 0;
  178. X        yySeconds = 0;
  179. X        yyMeridian = $2;
  180. X    }
  181. X    | tUNUMBER ':' tUNUMBER o_merid {
  182. X        yyHour = $1;
  183. X        yyMinutes = $3;
  184. X        yySeconds = 0;
  185. X        yyMeridian = $4;
  186. X    }
  187. X    | tUNUMBER ':' tUNUMBER tSNUMBER {
  188. X        yyHour = $1;
  189. X        yyMinutes = $3;
  190. X        yyMeridian = MER24;
  191. X        yyDSTmode = DSToff;
  192. X        yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
  193. X    }
  194. X    | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
  195. X        yyHour = $1;
  196. X        yyMinutes = $3;
  197. X        yySeconds = $5;
  198. X        yyMeridian = $6;
  199. X    }
  200. X    | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
  201. X        yyHour = $1;
  202. X        yyMinutes = $3;
  203. X        yySeconds = $5;
  204. X        yyMeridian = MER24;
  205. X        yyDSTmode = DSToff;
  206. X        yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
  207. X    }
  208. X    ;
  209. X
  210. Xzone    : tZONE {
  211. X        yyTimezone = $1;
  212. X        yyDSTmode = DSToff;
  213. X    }
  214. X    | tDAYZONE {
  215. X        yyTimezone = $1;
  216. X        yyDSTmode = DSTon;
  217. X    }
  218. X    ;
  219. X
  220. Xday    : tDAY {
  221. X        yyDayOrdinal = 1;
  222. X        yyDayNumber = $1;
  223. X    }
  224. X    | tDAY ',' {
  225. X        yyDayOrdinal = 1;
  226. X        yyDayNumber = $1;
  227. X    }
  228. X    | tUNUMBER tDAY {
  229. X        yyDayOrdinal = $1;
  230. X        yyDayNumber = $2;
  231. X    }
  232. X    ;
  233. X
  234. Xdate    : tUNUMBER '/' tUNUMBER {
  235. X        yyMonth = $1;
  236. X        yyDay = $3;
  237. X    }
  238. X    | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
  239. X        yyMonth = $1;
  240. X        yyDay = $3;
  241. X        yyYear = $5;
  242. X    }
  243. X    | tMONTH tUNUMBER {
  244. X        yyMonth = $1;
  245. X        yyDay = $2;
  246. X    }
  247. X    | tMONTH tUNUMBER ',' tUNUMBER {
  248. X        yyMonth = $1;
  249. X        yyDay = $2;
  250. X        yyYear = $4;
  251. X    }
  252. X    | tUNUMBER tMONTH {
  253. X        yyMonth = $2;
  254. X        yyDay = $1;
  255. X    }
  256. X    | tUNUMBER tMONTH tUNUMBER {
  257. X        yyMonth = $2;
  258. X        yyDay = $1;
  259. X        yyYear = $3;
  260. X    }
  261. X    ;
  262. X
  263. Xrel    : relunit tAGO {
  264. X        yyRelSeconds = -yyRelSeconds;
  265. X        yyRelMonth = -yyRelMonth;
  266. X    }
  267. X    | relunit
  268. X    ;
  269. X
  270. Xrelunit    : tUNUMBER tMINUTE_UNIT {
  271. X        yyRelSeconds += $1 * $2 * 60L;
  272. X    }
  273. X    | tSNUMBER tMINUTE_UNIT {
  274. X        yyRelSeconds += $1 * $2 * 60L;
  275. X    }
  276. X    | tMINUTE_UNIT {
  277. X        yyRelSeconds += $1 * 60L;
  278. X    }
  279. X    | tSNUMBER tSEC_UNIT {
  280. X        yyRelSeconds += $1;
  281. X    }
  282. X    | tUNUMBER tSEC_UNIT {
  283. X        yyRelSeconds += $1;
  284. X    }
  285. X    | tSEC_UNIT {
  286. X        yyRelSeconds++;
  287. X    }
  288. X    | tSNUMBER tMONTH_UNIT {
  289. X        yyRelMonth += $1 * $2;
  290. X    }
  291. X    | tUNUMBER tMONTH_UNIT {
  292. X        yyRelMonth += $1 * $2;
  293. X    }
  294. X    | tMONTH_UNIT {
  295. X        yyRelMonth += $1;
  296. X    }
  297. X    ;
  298. X
  299. Xnumber    : tUNUMBER {
  300. X        if (yyHaveTime && yyHaveDate && !yyHaveRel)
  301. X        yyYear = $1;
  302. X        else {
  303. X        yyHaveTime++;
  304. X        if ($1 < 100) {
  305. X            yyHour = $1;
  306. X            yyMinutes = 0;
  307. X        }
  308. X        else {
  309. X            yyHour = $1 / 100;
  310. X            yyMinutes = $1 % 100;
  311. X        }
  312. X        yySeconds = 0;
  313. X        yyMeridian = MER24;
  314. X        }
  315. X    }
  316. X    ;
  317. X
  318. Xo_merid    : /* NULL */ {
  319. X        $$ = MER24;
  320. X    }
  321. X    | tMERIDIAN {
  322. X        $$ = $1;
  323. X    }
  324. X    ;
  325. X
  326. X%%
  327. X
  328. X/* Month and day table. */
  329. Xstatic TABLE    MonthDayTable[] = {
  330. X    { "january",    tMONTH,  1 },
  331. X    { "february",    tMONTH,  2 },
  332. X    { "march",        tMONTH,  3 },
  333. X    { "april",        tMONTH,  4 },
  334. X    { "may",        tMONTH,  5 },
  335. X    { "june",        tMONTH,  6 },
  336. X    { "july",        tMONTH,  7 },
  337. X    { "august",        tMONTH,  8 },
  338. X    { "september",    tMONTH,  9 },
  339. X    { "sept",        tMONTH,  9 },
  340. X    { "october",    tMONTH, 10 },
  341. X    { "november",    tMONTH, 11 },
  342. X    { "december",    tMONTH, 12 },
  343. X    { "sunday",        tDAY, 0 },
  344. X    { "monday",        tDAY, 1 },
  345. X    { "tuesday",    tDAY, 2 },
  346. X    { "tues",        tDAY, 2 },
  347. X    { "wednesday",    tDAY, 3 },
  348. X    { "wednes",        tDAY, 3 },
  349. X    { "thursday",    tDAY, 4 },
  350. X    { "thur",        tDAY, 4 },
  351. X    { "thurs",        tDAY, 4 },
  352. X    { "friday",        tDAY, 5 },
  353. X    { "saturday",    tDAY, 6 },
  354. X    { NULL }
  355. X};
  356. X
  357. X/* Time units table. */
  358. Xstatic TABLE    UnitsTable[] = {
  359. X    { "year",        tMONTH_UNIT,    12 },
  360. X    { "month",        tMONTH_UNIT,    1 },
  361. X    { "fortnight",    tMINUTE_UNIT,    14 * 24 * 60 },
  362. X    { "week",        tMINUTE_UNIT,    7 * 24 * 60 },
  363. X    { "day",        tMINUTE_UNIT,    1 * 24 * 60 },
  364. X    { "hour",        tMINUTE_UNIT,    60 },
  365. X    { "minute",        tMINUTE_UNIT,    1 },
  366. X    { "min",        tMINUTE_UNIT,    1 },
  367. X    { "second",        tSEC_UNIT,    1 },
  368. X    { "sec",        tSEC_UNIT,    1 },
  369. X    { NULL }
  370. X};
  371. X
  372. X/* Assorted relative-time words. */
  373. Xstatic TABLE    OtherTable[] = {
  374. X    { "tomorrow",    tMINUTE_UNIT,    1 * 24 * 60 },
  375. X    { "yesterday",    tMINUTE_UNIT,    -1 * 24 * 60 },
  376. X    { "today",        tMINUTE_UNIT,    0 },
  377. X    { "now",        tMINUTE_UNIT,    0 },
  378. X    { "last",        tUNUMBER,    -1 },
  379. X    { "this",        tMINUTE_UNIT,    0 },
  380. X    { "next",        tUNUMBER,    2 },
  381. X    { "first",        tUNUMBER,    1 },
  382. X/*  { "second",        tUNUMBER,    2 }, */
  383. X    { "third",        tUNUMBER,    3 },
  384. X    { "fourth",        tUNUMBER,    4 },
  385. X    { "fifth",        tUNUMBER,    5 },
  386. X    { "sixth",        tUNUMBER,    6 },
  387. X    { "seventh",    tUNUMBER,    7 },
  388. X    { "eighth",        tUNUMBER,    8 },
  389. X    { "ninth",        tUNUMBER,    9 },
  390. X    { "tenth",        tUNUMBER,    10 },
  391. X    { "eleventh",    tUNUMBER,    11 },
  392. X    { "twelfth",    tUNUMBER,    12 },
  393. X    { "ago",        tAGO,    1 },
  394. X    { NULL }
  395. X};
  396. X
  397. X/* The timezone table. */
  398. Xstatic TABLE    TimezoneTable[] = {
  399. X    { "gmt",    tZONE,     HOUR( 0) },    /* Greenwich Mean */
  400. X    { "ut",    tZONE,     HOUR( 0) },    /* Universal (Coordinated) */
  401. X    { "utc",    tZONE,     HOUR( 0) },
  402. X    { "wet",    tZONE,     HOUR( 0) },    /* Western European */
  403. X    { "bst",    tDAYZONE,  HOUR( 0) },    /* British Summer */
  404. X    { "wat",    tZONE,     HOUR( 1) },    /* West Africa */
  405. X    { "at",    tZONE,     HOUR( 2) },    /* Azores */
  406. X#if    0
  407. X    /* For completeness.  BST is also British Summer, and GST is
  408. X     * also Guam Standard. */
  409. X    { "bst",    tZONE,     HOUR( 3) },    /* Brazil Standard */
  410. X    { "gst",    tZONE,     HOUR( 3) },    /* Greenland Standard */
  411. X#endif
  412. X    { "nft",    tZONE,     HOUR(3.5) },    /* Newfoundland */
  413. X    { "nst",    tZONE,     HOUR(3.5) },    /* Newfoundland Standard */
  414. X    { "ndt",    tDAYZONE,  HOUR(3.5) },    /* Newfoundland Daylight */
  415. X    { "ast",    tZONE,     HOUR( 4) },    /* Atlantic Standard */
  416. X    { "adt",    tDAYZONE,  HOUR( 4) },    /* Atlantic Daylight */
  417. X    { "est",    tZONE,     HOUR( 5) },    /* Eastern Standard */
  418. X    { "edt",    tDAYZONE,  HOUR( 5) },    /* Eastern Daylight */
  419. X    { "cst",    tZONE,     HOUR( 6) },    /* Central Standard */
  420. X    { "cdt",    tDAYZONE,  HOUR( 6) },    /* Central Daylight */
  421. X    { "mst",    tZONE,     HOUR( 7) },    /* Mountain Standard */
  422. X    { "mdt",    tDAYZONE,  HOUR( 7) },    /* Mountain Daylight */
  423. X    { "pst",    tZONE,     HOUR( 8) },    /* Pacific Standard */
  424. X    { "pdt",    tDAYZONE,  HOUR( 8) },    /* Pacific Daylight */
  425. X    { "yst",    tZONE,     HOUR( 9) },    /* Yukon Standard */
  426. X    { "ydt",    tDAYZONE,  HOUR( 9) },    /* Yukon Daylight */
  427. X    { "hst",    tZONE,     HOUR(10) },    /* Hawaii Standard */
  428. X    { "hdt",    tDAYZONE,  HOUR(10) },    /* Hawaii Daylight */
  429. X    { "cat",    tZONE,     HOUR(10) },    /* Central Alaska */
  430. X    { "ahst",    tZONE,     HOUR(10) },    /* Alaska-Hawaii Standard */
  431. X    { "nt",    tZONE,     HOUR(11) },    /* Nome */
  432. X    { "idlw",    tZONE,     HOUR(12) },    /* International Date Line West */
  433. X    { "cet",    tZONE,     -HOUR(1) },    /* Central European */
  434. X    { "met",    tZONE,     -HOUR(1) },    /* Middle European */
  435. X    { "mewt",    tZONE,     -HOUR(1) },    /* Middle European Winter */
  436. X    { "mest",    tDAYZONE,  -HOUR(1) },    /* Middle European Summer */
  437. X    { "swt",    tZONE,     -HOUR(1) },    /* Swedish Winter */
  438. X    { "sst",    tDAYZONE,  -HOUR(1) },    /* Swedish Summer */
  439. X    { "fwt",    tZONE,     -HOUR(1) },    /* French Winter */
  440. X    { "fst",    tDAYZONE,  -HOUR(1) },    /* French Summer */
  441. X    { "eet",    tZONE,     -HOUR(2) },    /* Eastern Europe, USSR Zone 1 */
  442. X    { "bt",    tZONE,     -HOUR(3) },    /* Baghdad, USSR Zone 2 */
  443. X    { "it",    tZONE,     -HOUR(3.5) },/* Iran */
  444. X    { "zp4",    tZONE,     -HOUR(4) },    /* USSR Zone 3 */
  445. X    { "zp5",    tZONE,     -HOUR(5) },    /* USSR Zone 4 */
  446. X    { "ist",    tZONE,     -HOUR(5.5) },/* Indian Standard */
  447. X    { "zp6",    tZONE,     -HOUR(6) },    /* USSR Zone 5 */
  448. X#if    0
  449. X    /* For completeness.  NST is also Newfoundland Stanard, nad SST is
  450. X     * also Swedish Summer. */
  451. X    { "nst",    tZONE,     -HOUR(6.5) },/* North Sumatra */
  452. X    { "sst",    tZONE,     -HOUR(7) },    /* South Sumatra, USSR Zone 6 */
  453. X#endif    /* 0 */
  454. X    { "wast",    tZONE,     -HOUR(7) },    /* West Australian Standard */
  455. X    { "wadt",    tDAYZONE,  -HOUR(7) },    /* West Australian Daylight */
  456. X    { "jt",    tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
  457. X    { "cct",    tZONE,     -HOUR(8) },    /* China Coast, USSR Zone 7 */
  458. X    { "jst",    tZONE,     -HOUR(9) },    /* Japan Standard, USSR Zone 8 */
  459. X    { "cast",    tZONE,     -HOUR(9.5) },/* Central Australian Standard */
  460. X    { "cadt",    tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
  461. X    { "east",    tZONE,     -HOUR(10) },    /* Eastern Australian Standard */
  462. X    { "eadt",    tDAYZONE,  -HOUR(10) },    /* Eastern Australian Daylight */
  463. X    { "gst",    tZONE,     -HOUR(10) },    /* Guam Standard, USSR Zone 9 */
  464. X    { "nzt",    tZONE,     -HOUR(12) },    /* New Zealand */
  465. X    { "nzst",    tZONE,     -HOUR(12) },    /* New Zealand Standard */
  466. X    { "nzdt",    tDAYZONE,  -HOUR(12) },    /* New Zealand Daylight */
  467. X    { "idle",    tZONE,     -HOUR(12) },    /* International Date Line East */
  468. X    {  NULL  }
  469. X};
  470. X
  471. X/* Military timezone table. */
  472. Xstatic TABLE    MilitaryTable[] = {
  473. X    { "a",    tZONE,    HOUR(  1) },
  474. X    { "b",    tZONE,    HOUR(  2) },
  475. X    { "c",    tZONE,    HOUR(  3) },
  476. X    { "d",    tZONE,    HOUR(  4) },
  477. X    { "e",    tZONE,    HOUR(  5) },
  478. X    { "f",    tZONE,    HOUR(  6) },
  479. X    { "g",    tZONE,    HOUR(  7) },
  480. X    { "h",    tZONE,    HOUR(  8) },
  481. X    { "i",    tZONE,    HOUR(  9) },
  482. X    { "k",    tZONE,    HOUR( 10) },
  483. X    { "l",    tZONE,    HOUR( 11) },
  484. X    { "m",    tZONE,    HOUR( 12) },
  485. X    { "n",    tZONE,    HOUR(- 1) },
  486. X    { "o",    tZONE,    HOUR(- 2) },
  487. X    { "p",    tZONE,    HOUR(- 3) },
  488. X    { "q",    tZONE,    HOUR(- 4) },
  489. X    { "r",    tZONE,    HOUR(- 5) },
  490. X    { "s",    tZONE,    HOUR(- 6) },
  491. X    { "t",    tZONE,    HOUR(- 7) },
  492. X    { "u",    tZONE,    HOUR(- 8) },
  493. X    { "v",    tZONE,    HOUR(- 9) },
  494. X    { "w",    tZONE,    HOUR(-10) },
  495. X    { "x",    tZONE,    HOUR(-11) },
  496. X    { "y",    tZONE,    HOUR(-12) },
  497. X    { "z",    tZONE,    HOUR(  0) },
  498. X    { NULL }
  499. X};
  500. X
  501. X
  502. X
  503. X
  504. X/* ARGSUSED */
  505. Xstatic
  506. Xyyerror(s)
  507. X    char    *s;
  508. X{
  509. X}
  510. X
  511. X
  512. Xstatic time_t
  513. XToSeconds(Hours, Minutes, Seconds, Meridian)
  514. X    time_t    Hours;
  515. X    time_t    Minutes;
  516. X    time_t    Seconds;
  517. X    MERIDIAN    Meridian;
  518. X{
  519. X    if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
  520. X    return -1;
  521. X    switch (Meridian) {
  522. X    case MER24:
  523. X    if (Hours < 0 || Hours > 23)
  524. X        return -1;
  525. X    return (Hours * 60L + Minutes) * 60L + Seconds;
  526. X    case MERam:
  527. X    if (Hours < 1 || Hours > 12)
  528. X        return -1;
  529. X    return (Hours * 60L + Minutes) * 60L + Seconds;
  530. X    case MERpm:
  531. X    if (Hours < 1 || Hours > 12)
  532. X        return -1;
  533. X    return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
  534. X    }
  535. X    /* NOTREACHED */
  536. X}
  537. X
  538. X
  539. Xstatic time_t
  540. XConvert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
  541. X    time_t    Month;
  542. X    time_t    Day;
  543. X    time_t    Year;
  544. X    time_t    Hours;
  545. X    time_t    Minutes;
  546. X    time_t    Seconds;
  547. X    MERIDIAN    Meridian;
  548. X    DSTMODE    DSTmode;
  549. X{
  550. X    static int    DaysInMonth[12] = {
  551. X    31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  552. X    };
  553. X    time_t    tod;
  554. X    time_t    Julian;
  555. X    int        i;
  556. X
  557. X    if (Year < 0)
  558. X    Year = -Year;
  559. X    if (Year < 100)
  560. X    Year += 1900;
  561. X    DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
  562. X            ? 29 : 28;
  563. X    if (Year < EPOCH || Year > 1999
  564. X     || Month < 1 || Month > 12
  565. X     /* Lint fluff:  "conversion from long may lose accuracy" */
  566. X     || Day < 1 || Day > DaysInMonth[(int)--Month])
  567. X    return -1;
  568. X
  569. X    for (Julian = Day - 1, i = 0; i < Month; i++)
  570. X    Julian += DaysInMonth[i];
  571. X    for (i = EPOCH; i < Year; i++)
  572. X    Julian += 365 + (i % 4 == 0);
  573. X    Julian *= SECSPERDAY;
  574. X    Julian += yyTimezone * 60L;
  575. X    if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
  576. X    return -1;
  577. X    Julian += tod;
  578. X    if (DSTmode == DSTon
  579. X     || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
  580. X    Julian -= 60 * 60;
  581. X    return Julian;
  582. X}
  583. X
  584. X
  585. Xstatic time_t
  586. XDSTcorrect(Start, Future)
  587. X    time_t    Start;
  588. X    time_t    Future;
  589. X{
  590. X    time_t    StartDay;
  591. X    time_t    FutureDay;
  592. X
  593. X    StartDay = (localtime(&Start)->tm_hour + 1) % 24;
  594. X    FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
  595. X    return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
  596. X}
  597. X
  598. X
  599. Xstatic time_t
  600. XRelativeDate(Start, DayOrdinal, DayNumber)
  601. X    time_t    Start;
  602. X    time_t    DayOrdinal;
  603. X    time_t    DayNumber;
  604. X{
  605. X    struct tm    *tm;
  606. X    time_t    now;
  607. X
  608. X    now = Start;
  609. X    tm = localtime(&now);
  610. X    now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
  611. X    now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
  612. X    return DSTcorrect(Start, now);
  613. X}
  614. X
  615. X
  616. Xstatic time_t
  617. XRelativeMonth(Start, RelMonth)
  618. X    time_t    Start;
  619. X    time_t    RelMonth;
  620. X{
  621. X    struct tm    *tm;
  622. X    time_t    Month;
  623. X    time_t    Year;
  624. X
  625. X    if (RelMonth == 0)
  626. X    return 0;
  627. X    tm = localtime(&Start);
  628. X    Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
  629. X    Year = Month / 12;
  630. X    Month = Month % 12 + 1;
  631. X    return DSTcorrect(Start,
  632. X        Convert(Month, (time_t)tm->tm_mday, Year,
  633. X        (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
  634. X        MER24, DSTmaybe));
  635. X}
  636. X
  637. X
  638. Xstatic int
  639. XLookupWord(buff)
  640. X    char        *buff;
  641. X{
  642. X    register char    *p;
  643. X    register char    *q;
  644. X    register TABLE    *tp;
  645. X    int            i;
  646. X    int            abbrev;
  647. X
  648. X    /* Make it lowercase. */
  649. X    for (p = buff; *p; p++)
  650. X    if (isupper(*p))
  651. X        *p = tolower(*p);
  652. X
  653. X    if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
  654. X    yylval.Meridian = MERam;
  655. X    return tMERIDIAN;
  656. X    }
  657. X    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
  658. X    yylval.Meridian = MERpm;
  659. X    return tMERIDIAN;
  660. X    }
  661. X
  662. X    /* See if we have an abbreviation for a month. */
  663. X    if (strlen(buff) == 3)
  664. X    abbrev = 1;
  665. X    else if (strlen(buff) == 4 && buff[3] == '.') {
  666. X    abbrev = 1;
  667. X    buff[3] = '\0';
  668. X    }
  669. X    else
  670. X    abbrev = 0;
  671. X
  672. X    for (tp = MonthDayTable; tp->name; tp++) {
  673. X    if (abbrev) {
  674. X        if (strncmp(buff, tp->name, 3) == 0) {
  675. X        yylval.Number = tp->value;
  676. X        return tp->type;
  677. X        }
  678. X    }
  679. X    else if (strcmp(buff, tp->name) == 0) {
  680. X        yylval.Number = tp->value;
  681. X        return tp->type;
  682. X    }
  683. X    }
  684. X
  685. X    for (tp = TimezoneTable; tp->name; tp++)
  686. X    if (strcmp(buff, tp->name) == 0) {
  687. X        yylval.Number = tp->value;
  688. X        return tp->type;
  689. X    }
  690. X
  691. X    for (tp = UnitsTable; tp->name; tp++)
  692. X    if (strcmp(buff, tp->name) == 0) {
  693. X        yylval.Number = tp->value;
  694. X        return tp->type;
  695. X    }
  696. X
  697. X    /* Strip off any plural and try the units table again. */
  698. X    i = strlen(buff) - 1;
  699. X    if (buff[i] == 's') {
  700. X    buff[i] = '\0';
  701. X    for (tp = UnitsTable; tp->name; tp++)
  702. X        if (strcmp(buff, tp->name) == 0) {
  703. X        yylval.Number = tp->value;
  704. X        return tp->type;
  705. X        }
  706. X    }
  707. X
  708. X    for (tp = OtherTable; tp->name; tp++)
  709. X    if (strcmp(buff, tp->name) == 0) {
  710. X        yylval.Number = tp->value;
  711. X        return tp->type;
  712. X    }
  713. X
  714. X    /* Military timezones. */
  715. X    if (buff[1] == '\0' && isalpha(*buff)) {
  716. X    for (tp = MilitaryTable; tp->name; tp++)
  717. X        if (strcmp(buff, tp->name) == 0) {
  718. X        yylval.Number = tp->value;
  719. X        return tp->type;
  720. X        }
  721. X    }
  722. X
  723. X    /* Drop out any periods and try the timezone table again. */
  724. X    for (i = 0, p = q = buff; *q; q++)
  725. X    if (*q != '.')
  726. X        *p++ = *q;
  727. X    else
  728. X        i++;
  729. X    *p = '\0';
  730. X    if (i)
  731. X    for (tp = TimezoneTable; tp->name; tp++)
  732. X        if (strcmp(buff, tp->name) == 0) {
  733. X        yylval.Number = tp->value;
  734. X        return tp->type;
  735. X        }
  736. X
  737. X    return tID;
  738. X}
  739. X
  740. X
  741. Xstatic int
  742. Xyylex()
  743. X{
  744. X    register char    c;
  745. X    register char    *p;
  746. X    char        buff[20];
  747. X    int            Count;
  748. X    int            sign;
  749. X
  750. X    for ( ; ; ) {
  751. X    while (isspace(*yyInput))
  752. X        yyInput++;
  753. X
  754. X    if (isdigit(c = *yyInput) || c == '-' || c == '+') {
  755. X        if (c == '-' || c == '+') {
  756. X        sign = c == '-' ? -1 : 1;
  757. X        if (!isdigit(*++yyInput))
  758. X            /* skip the '-' sign */
  759. X            continue;
  760. X        }
  761. X        else
  762. X        sign = 0;
  763. X        for (yylval.Number = 0; isdigit(c = *yyInput++); )
  764. X        yylval.Number = 10 * yylval.Number + c - '0';
  765. X        yyInput--;
  766. X        if (sign < 0)
  767. X        yylval.Number = -yylval.Number;
  768. X        return sign ? tSNUMBER : tUNUMBER;
  769. X    }
  770. X    if (isalpha(c)) {
  771. X        for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
  772. X        if (p < &buff[sizeof buff - 1])
  773. X            *p++ = c;
  774. X        *p = '\0';
  775. X        yyInput--;
  776. X        return LookupWord(buff);
  777. X    }
  778. X    if (c != '(')
  779. X        return *yyInput++;
  780. X    Count = 0;
  781. X    do {
  782. X        c = *yyInput++;
  783. X        if (c == '\0')
  784. X        return c;
  785. X        if (c == '(')
  786. X        Count++;
  787. X        else if (c == ')')
  788. X        Count--;
  789. X    } while (Count > 0);
  790. X    }
  791. X}
  792. X
  793. X
  794. Xtime_t
  795. Xgetdate(p, now)
  796. X    char        *p;
  797. X    struct timeb    *now;
  798. X{
  799. X    struct tm        *tm;
  800. X    struct timeb    ftz;
  801. X    time_t        Start;
  802. X    time_t        tod;
  803. X
  804. X    yyInput = p;
  805. X    if (now == NULL) {
  806. X    now = &ftz;
  807. X#if    defined(NEED_TZSET)
  808. X    (void)time(&ftz.time);
  809. X    /* Set the timezone global. */
  810. X    tzset();
  811. X    ftz.timezone = (int) timezone / 60;
  812. X#else
  813. X    (void)ftime(&ftz);
  814. X#endif    /* defined(NEED_TZSET) */
  815. X    }
  816. X
  817. X    tm = localtime(&now->time);
  818. X    yyYear = tm->tm_year;
  819. X    yyMonth = tm->tm_mon + 1;
  820. X    yyDay = tm->tm_mday;
  821. X    yyTimezone = now->timezone;
  822. X    yyDSTmode = DSTmaybe;
  823. X    yyHour = 0;
  824. X    yyMinutes = 0;
  825. X    yySeconds = 0;
  826. X    yyMeridian = MER24;
  827. X    yyRelSeconds = 0;
  828. X    yyRelMonth = 0;
  829. X    yyHaveDate = 0;
  830. X    yyHaveDay = 0;
  831. X    yyHaveRel = 0;
  832. X    yyHaveTime = 0;
  833. X    yyHaveZone = 0;
  834. X
  835. X    if (yyparse()
  836. X     || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
  837. X    return -1;
  838. X
  839. X    if (yyHaveDate || yyHaveTime || yyHaveDay) {
  840. X    Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
  841. X            yyMeridian, yyDSTmode);
  842. X    if (Start < 0)
  843. X        return -1;
  844. X    }
  845. X    else {
  846. X    Start = now->time;
  847. X    if (!yyHaveRel)
  848. X        Start -= ((tm->tm_hour * 60L) + tm->tm_min * 60L) + tm->tm_sec;
  849. X    }
  850. X
  851. X    Start += yyRelSeconds;
  852. X    Start += RelativeMonth(Start, yyRelMonth);
  853. X
  854. X    if (yyHaveDay && !yyHaveDate) {
  855. X    tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
  856. X    Start += tod;
  857. X    }
  858. X
  859. X    /* Have to do *something* with a legitimate -1 so it's distinguishable
  860. X     * from the error return value.  (Alternately could set errno on error.) */
  861. X    return Start == -1 ? 0 : Start;
  862. X}
  863. X
  864. X
  865. X#if    defined(TEST)
  866. X
  867. X/* ARGSUSED */
  868. Xmain(ac, av)
  869. X    int        ac;
  870. X    char    *av[];
  871. X{
  872. X    char    buff[128];
  873. X    time_t    d;
  874. X
  875. X    (void)printf("Enter date, or blank line to exit.\n\t> ");
  876. X    (void)fflush(stdout);
  877. X    while (gets(buff) && buff[0]) {
  878. X    d = getdate(buff, (struct timeb *)NULL);
  879. X    if (d == -1)
  880. X        (void)printf("Bad format - couldn't convert.\n");
  881. X    else
  882. X        (void)printf("%s", ctime(&d));
  883. X    (void)printf("\t> ");
  884. X    (void)fflush(stdout);
  885. X    }
  886. X    exit(0);
  887. X    /* NOTREACHED */
  888. X}
  889. X#endif    /* defined(TEST) */
  890. END_OF_FILE
  891. if test 20818 -ne `wc -c <'getdate.y'`; then
  892.     echo shar: \"'getdate.y'\" unpacked with wrong size!
  893. fi
  894. # end of 'getdate.y'
  895. fi
  896. if test -f 'mkdir.c' -a "${1}" != "-c" ; then 
  897.   echo shar: Will not clobber existing file \"'mkdir.c'\"
  898. else
  899. echo shar: Extracting \"'mkdir.c'\" \(4832 characters\)
  900. sed "s/^X//" >'mkdir.c' <<'END_OF_FILE'
  901. X/****************************************************************************
  902. X
  903. XNAME
  904. X   mkdir.c -- emulation of BSD/SVr3-style mkdir(2) system call
  905. X
  906. XSYNOPSIS
  907. X   int mkdir(path, perm)    -- make a directory with given permissions
  908. X   char *path; int perm;
  909. X
  910. XDESCRIPTION
  911. X   The mkdir() function is used for making directories on systems that
  912. Xdon't have a mkdir(2) call (that is, V7 and USG systems before V.3). It tries
  913. Xto act as much like mkdir(2) as possible. Due to various bogosities (why, oh
  914. Xwhy wasn't mknod(2) for a directory made a non-privileged call?) it cannot
  915. Xcompletely succeed. It returns 0 on success and -1 on failure but
  916. Xonly detect the following ERRNO conditions; ENOENT, EEXIST, EACCESS, ENOTDIR.
  917. X
  918. X   Note: this function emulates the SVr3 behavior (group ID of the directory
  919. Xis the effective group ID of the calling process) rather than the BSD
  920. Xbehavior (group ID of the directory is the group ID of the parent directory).
  921. X
  922. X   On USG it will succeed if the real or apparent uid of the calling process
  923. Xhas write privileges in the current directory (the latter case is implemented
  924. Xby a kluge that tries to set the parent directory's permissions to 0777, 'ware
  925. Xsecurity holes!). The new directory will be owned by the effective uid.
  926. X
  927. X   On V7 (because it restricts the chown(2) call and mkdir(1) makes
  928. Xdirectories owned by the real ID of its caller) the call will only succeed
  929. Xif the real ID matches, and the new directory will be owned by the real
  930. Xuid.
  931. X
  932. XREVISED BY
  933. X   Eric S. Raymond
  934. X
  935. X****************************************************************************/
  936. X/* LINTLIBRARY */
  937. X#include <sys/types.h>
  938. X#include <sys/stat.h>
  939. X#include <errno.h>
  940. X#include <signal.h>
  941. X
  942. Xextern int errno;
  943. X
  944. Xstatic int fwait(pid)
  945. X/* wait on a child process, shielding it from SIGINT and SIGHUP */
  946. Xregister int pid;
  947. X{
  948. X    register int w;
  949. X    int status;
  950. X
  951. X    while ((w = wait(&status)) != pid && w != -1)
  952. X    continue;
  953. X    if (w == -1)
  954. X    status = -1;
  955. X
  956. X    return(status);
  957. X}
  958. X
  959. Xint mkdir(path, perm)
  960. Xchar *path;
  961. Xint perm;
  962. X{
  963. X    int            status, pid;
  964. X    int            uid = getuid(), gid = getgid();
  965. X#ifndef lint
  966. X    int            euid = geteuid();
  967. X    int            egid = getegid();
  968. X#endif /* lint */
  969. X    struct stat        pstat, sbuf;
  970. X    register char   *p;
  971. X    char        parent[200];
  972. X    extern char        *strrchr();
  973. X
  974. X#ifdef MAIN
  975. X    (void) fprintf(stderr, "Attempting to mkdir %s\n", path);
  976. X#endif /* MAIN */
  977. X
  978. X    errno = 0;
  979. X
  980. X    /*
  981. X     * check that the directory doesn't already exist, so that the
  982. X     * do loop below must run at least once
  983. X     */
  984. X    if (stat(path, &sbuf) == 0)
  985. X    {
  986. X    errno = EEXIST;
  987. X#ifdef MAIN
  988. X    (void) fprintf(stderr, "Directory %s exists\n", path);
  989. X#endif /* MAIN */
  990. X    return(-1);
  991. X    }
  992. X
  993. X    /* construct the parent's name */
  994. X    if (p = strrchr(path, '/'))
  995. X    {
  996. X    *p = '\0';
  997. X    (void) strcpy(parent, path);
  998. X    *p = '/';
  999. X    }
  1000. X    else
  1001. X    (void) strcpy(parent, ".");
  1002. X
  1003. X    if (stat(parent, &pstat) == -1)    /* check that the parent exists */
  1004. X    {
  1005. X    errno = ENOENT;
  1006. X    return(-1);
  1007. X    }
  1008. X    else if (!(pstat.st_mode & S_IFDIR))    /* and that it's a directory */
  1009. X    {
  1010. X    errno = ENOTDIR;
  1011. X    return(-1);
  1012. X    }
  1013. X
  1014. X#ifdef USG
  1015. X    /*
  1016. X     * If the parent directory is 755 (rwxr-xr-x) the mkdir(1) below
  1017. X     * will probably fail because it will get suid'd to our real uid, which
  1018. X     * is random (and thus probably won't match the parent owner's).
  1019. X     * So we have to temporarily chmod the parent to 777 (rwxrwxrwx).
  1020. X     */
  1021. X    if (sbuf.st_uid != uid)
  1022. X    {
  1023. X    if (chmod(parent, 0777) == -1)
  1024. X    {
  1025. X        errno = EACCES;
  1026. X        return(-1);
  1027. X    }
  1028. X    }
  1029. X#endif /* USG */
  1030. X
  1031. X    /* now we can make the new directory */
  1032. X    if (pid = fork())    /* parent side */
  1033. X    {
  1034. X    if (pid == -1)
  1035. X        return(-1);
  1036. X
  1037. X    status = fwait(pid);    /* wait till mkdir child is done */
  1038. X
  1039. X#ifdef USG
  1040. X    /*
  1041. X     * Spawn another child to set ownership correctly -- we do this so
  1042. X     * that it gets set to effective ID even if we're running su. This
  1043. X     * only works where chown(2) can be called to give files away by a
  1044. X     * non-superuser.
  1045. X     */
  1046. X    if (pid = fork())
  1047. X        (void) fwait(pid);
  1048. X    else {
  1049. X#ifndef lint
  1050. X        int            oldumask = umask(0777);
  1051. X#endif /* lint */
  1052. X
  1053. X        (void) stat(".", &pstat);
  1054. X        (void) setuid(uid);
  1055. X        (void) setgid(gid);
  1056. X#ifndef lint        /* USG lints disagree about 2nd argument types */
  1057. X        (void) chmod(path, (unsigned)(perm & ~oldumask));
  1058. X        (void) chown(path, euid, egid);
  1059. X        (void) umask(oldumask);
  1060. X#endif /* lint */
  1061. X        _exit(0);
  1062. X    }
  1063. X#endif /* USG */
  1064. X    } else {        /* child side */
  1065. X    (void) close(1);    /* stdout */
  1066. X    (void) close(2);    /* stderr */
  1067. X    (void) execlp("mkdir", "mkdir", path, (char *)0);
  1068. X    perror(path);
  1069. X    _exit(1);
  1070. X    }
  1071. X
  1072. X#ifndef lint    /* USG lints disagree about the type of arg 2 */
  1073. X#ifdef USG
  1074. X    if (sbuf.st_uid != uid)
  1075. X    (void) chmod(parent, (unsigned) pstat.st_mode);    /* put it back */
  1076. X#endif /* USG */
  1077. X#endif /* lint */
  1078. X
  1079. X    return(status);
  1080. X}
  1081. X
  1082. X/* mkdir.c ends here */
  1083. END_OF_FILE
  1084. if test 4832 -ne `wc -c <'mkdir.c'`; then
  1085.     echo shar: \"'mkdir.c'\" unpacked with wrong size!
  1086. fi
  1087. # end of 'mkdir.c'
  1088. fi
  1089. if test -f 'random.c' -a "${1}" != "-c" ; then 
  1090.   echo shar: Will not clobber existing file \"'random.c'\"
  1091. else
  1092. echo shar: Extracting \"'random.c'\" \(12793 characters\)
  1093. sed "s/^X//" >'random.c' <<'END_OF_FILE'
  1094. X/*
  1095. X * Copyright (c) 1983 Regents of the University of California.
  1096. X * All rights reserved.
  1097. X *
  1098. X * Redistribution and use in source and binary forms are permitted
  1099. X * provided that the above copyright notice and this paragraph are
  1100. X * duplicated in all such forms and that any documentation,
  1101. X * advertising materials, and other materials related to such
  1102. X * distribution and use acknowledge that the software was developed
  1103. X * by the University of California, Berkeley.  The name of the
  1104. X * University may not be used to endorse or promote products derived
  1105. X * from this software without specific prior written permission.
  1106. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1107. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1108. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1109. X */
  1110. X
  1111. X#if defined(LIBC_SCCS) && !defined(lint)
  1112. Xstatic char sccsid[] = "@(#)random.c    5.5 (Berkeley) 7/6/88";
  1113. X#endif /* LIBC_SCCS and not lint */
  1114. X
  1115. X#include <stdio.h>
  1116. X
  1117. X/*
  1118. X * random.c:
  1119. X * An improved random number generation package.  In addition to the standard
  1120. X * rand()/srand() like interface, this package also has a special state info
  1121. X * interface.  The initstate() routine is called with a seed, an array of
  1122. X * bytes, and a count of how many bytes are being passed in; this array is then
  1123. X * initialized to contain information for random number generation with that
  1124. X * much state information.  Good sizes for the amount of state information are
  1125. X * 32, 64, 128, and 256 bytes.  The state can be switched by calling the
  1126. X * setstate() routine with the same array as was initiallized with initstate().
  1127. X * By default, the package runs with 128 bytes of state information and
  1128. X * generates far better random numbers than a linear congruential generator.
  1129. X * If the amount of state information is less than 32 bytes, a simple linear
  1130. X * congruential R.N.G. is used.
  1131. X * Internally, the state information is treated as an array of longs; the
  1132. X * zeroeth element of the array is the type of R.N.G. being used (small
  1133. X * integer); the remainder of the array is the state information for the
  1134. X * R.N.G.  Thus, 32 bytes of state information will give 7 longs worth of
  1135. X * state information, which will allow a degree seven polynomial.  (Note: the 
  1136. X * zeroeth word of state information also has some other information stored
  1137. X * in it -- see setstate() for details).
  1138. X * The random number generation technique is a linear feedback shift register
  1139. X * approach, employing trinomials (since there are fewer terms to sum up that
  1140. X * way).  In this approach, the least significant bit of all the numbers in
  1141. X * the state table will act as a linear feedback shift register, and will have
  1142. X * period 2^deg - 1 (where deg is the degree of the polynomial being used,
  1143. X * assuming that the polynomial is irreducible and primitive).  The higher
  1144. X * order bits will have longer periods, since their values are also influenced
  1145. X * by pseudo-random carries out of the lower bits.  The total period of the
  1146. X * generator is approximately deg*(2**deg - 1); thus doubling the amount of
  1147. X * state information has a vast influence on the period of the generator.
  1148. X * Note: the deg*(2**deg - 1) is an approximation only good for large deg,
  1149. X * when the period of the shift register is the dominant factor.  With deg
  1150. X * equal to seven, the period is actually much longer than the 7*(2**7 - 1)
  1151. X * predicted by this formula.
  1152. X */
  1153. X
  1154. X
  1155. X
  1156. X/*
  1157. X * For each of the currently supported random number generators, we have a
  1158. X * break value on the amount of state information (you need at least this
  1159. X * many bytes of state info to support this random number generator), a degree
  1160. X * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
  1161. X * the separation between the two lower order coefficients of the trinomial.
  1162. X */
  1163. X
  1164. X#define        TYPE_0        0        /* linear congruential */
  1165. X#define        BREAK_0        8
  1166. X#define        DEG_0        0
  1167. X#define        SEP_0        0
  1168. X
  1169. X#define        TYPE_1        1        /* x**7 + x**3 + 1 */
  1170. X#define        BREAK_1        32
  1171. X#define        DEG_1        7
  1172. X#define        SEP_1        3
  1173. X
  1174. X#define        TYPE_2        2        /* x**15 + x + 1 */
  1175. X#define        BREAK_2        64
  1176. X#define        DEG_2        15
  1177. X#define        SEP_2        1
  1178. X
  1179. X#define        TYPE_3        3        /* x**31 + x**3 + 1 */
  1180. X#define        BREAK_3        128
  1181. X#define        DEG_3        31
  1182. X#define        SEP_3        3
  1183. X
  1184. X#define        TYPE_4        4        /* x**63 + x + 1 */
  1185. X#define        BREAK_4        256
  1186. X#define        DEG_4        63
  1187. X#define        SEP_4        1
  1188. X
  1189. X
  1190. X/*
  1191. X * Array versions of the above information to make code run faster -- relies
  1192. X * on fact that TYPE_i == i.
  1193. X */
  1194. X
  1195. X#define        MAX_TYPES    5        /* max number of types above */
  1196. X
  1197. Xstatic  int        degrees[ MAX_TYPES ]    = { DEG_0, DEG_1, DEG_2,
  1198. X                                DEG_3, DEG_4 };
  1199. X
  1200. Xstatic  int        seps[ MAX_TYPES ]    = { SEP_0, SEP_1, SEP_2,
  1201. X                                SEP_3, SEP_4 };
  1202. X
  1203. X
  1204. X
  1205. X/*
  1206. X * Initially, everything is set up as if from :
  1207. X *        initstate( 1, &randtbl, 128 );
  1208. X * Note that this initialization takes advantage of the fact that srandom()
  1209. X * advances the front and rear pointers 10*rand_deg times, and hence the
  1210. X * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
  1211. X * element of the state information, which contains info about the current
  1212. X * position of the rear pointer is just
  1213. X *    MAX_TYPES*(rptr - state) + TYPE_3 == TYPE_3.
  1214. X */
  1215. X
  1216. Xstatic  long        randtbl[ DEG_3 + 1 ]    = { TYPE_3,
  1217. X                0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 
  1218. X                0xde3b81e0, 0xdf0a6fb5, 0xf103bc02, 0x48f340fb, 
  1219. X                0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 
  1220. X                0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 
  1221. X                0xda672e2a, 0x1588ca88, 0xe369735d, 0x904f35f7, 
  1222. X                0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 
  1223. X                0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 
  1224. X                    0xf5ad9d0e, 0x8999220b, 0x27fb47b9 };
  1225. X
  1226. X/*
  1227. X * fptr and rptr are two pointers into the state info, a front and a rear
  1228. X * pointer.  These two pointers are always rand_sep places aparts, as they cycle
  1229. X * cyclically through the state information.  (Yes, this does mean we could get
  1230. X * away with just one pointer, but the code for random() is more efficient this
  1231. X * way).  The pointers are left positioned as they would be from the call
  1232. X *            initstate( 1, randtbl, 128 )
  1233. X * (The position of the rear pointer, rptr, is really 0 (as explained above
  1234. X * in the initialization of randtbl) because the state table pointer is set
  1235. X * to point to randtbl[1] (as explained below).
  1236. X */
  1237. X
  1238. Xstatic  long        *fptr            = &randtbl[ SEP_3 + 1 ];
  1239. Xstatic  long        *rptr            = &randtbl[ 1 ];
  1240. X
  1241. X
  1242. X
  1243. X/*
  1244. X * The following things are the pointer to the state information table,
  1245. X * the type of the current generator, the degree of the current polynomial
  1246. X * being used, and the separation between the two pointers.
  1247. X * Note that for efficiency of random(), we remember the first location of
  1248. X * the state information, not the zeroeth.  Hence it is valid to access
  1249. X * state[-1], which is used to store the type of the R.N.G.
  1250. X * Also, we remember the last location, since this is more efficient than
  1251. X * indexing every time to find the address of the last element to see if
  1252. X * the front and rear pointers have wrapped.
  1253. X */
  1254. X
  1255. Xstatic  long        *state            = &randtbl[ 1 ];
  1256. X
  1257. Xstatic  int        rand_type        = TYPE_3;
  1258. Xstatic  int        rand_deg        = DEG_3;
  1259. Xstatic  int        rand_sep        = SEP_3;
  1260. X
  1261. Xstatic  long        *end_ptr        = &randtbl[ DEG_3 + 1 ];
  1262. X
  1263. X
  1264. X
  1265. X/*
  1266. X * srandom:
  1267. X * Initialize the random number generator based on the given seed.  If the
  1268. X * type is the trivial no-state-information type, just remember the seed.
  1269. X * Otherwise, initializes state[] based on the given "seed" via a linear
  1270. X * congruential generator.  Then, the pointers are set to known locations
  1271. X * that are exactly rand_sep places apart.  Lastly, it cycles the state
  1272. X * information a given number of times to get rid of any initial dependencies
  1273. X * introduced by the L.C.R.N.G.
  1274. X * Note that the initialization of randtbl[] for default usage relies on
  1275. X * values produced by this routine.
  1276. X */
  1277. X
  1278. Xsrandom( x )
  1279. X
  1280. X    unsigned        x;
  1281. X{
  1282. X        register  int        i, j;
  1283. X    long random();
  1284. X
  1285. X    if(  rand_type  ==  TYPE_0  )  {
  1286. X        state[ 0 ] = x;
  1287. X    }
  1288. X    else  {
  1289. X        j = 1;
  1290. X        state[ 0 ] = x;
  1291. X        for( i = 1; i < rand_deg; i++ )  {
  1292. X        state[i] = 1103515245*state[i - 1] + 12345;
  1293. X        }
  1294. X        fptr = &state[ rand_sep ];
  1295. X        rptr = &state[ 0 ];
  1296. X        for( i = 0; i < 10*rand_deg; i++ )  random();
  1297. X    }
  1298. X}
  1299. X
  1300. X
  1301. X
  1302. X/*
  1303. X * initstate:
  1304. X * Initialize the state information in the given array of n bytes for
  1305. X * future random number generation.  Based on the number of bytes we
  1306. X * are given, and the break values for the different R.N.G.'s, we choose
  1307. X * the best (largest) one we can and set things up for it.  srandom() is
  1308. X * then called to initialize the state information.
  1309. X * Note that on return from srandom(), we set state[-1] to be the type
  1310. X * multiplexed with the current value of the rear pointer; this is so
  1311. X * successive calls to initstate() won't lose this information and will
  1312. X * be able to restart with setstate().
  1313. X * Note: the first thing we do is save the current state, if any, just like
  1314. X * setstate() so that it doesn't matter when initstate is called.
  1315. X * Returns a pointer to the old state.
  1316. X */
  1317. X
  1318. Xchar  *
  1319. Xinitstate( seed, arg_state, n )
  1320. X
  1321. X    unsigned        seed;            /* seed for R. N. G. */
  1322. X    char        *arg_state;        /* pointer to state array */
  1323. X    int            n;            /* # bytes of state info */
  1324. X{
  1325. X    register  char        *ostate        = (char *)( &state[ -1 ] );
  1326. X
  1327. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  1328. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  1329. X    if(  n  <  BREAK_1  )  {
  1330. X        if(  n  <  BREAK_0  )  {
  1331. X        fprintf( stderr, "initstate: not enough state (%d bytes) with which to do jack; ignored.\n", n );
  1332. X        return;
  1333. X        }
  1334. X        rand_type = TYPE_0;
  1335. X        rand_deg = DEG_0;
  1336. X        rand_sep = SEP_0;
  1337. X    }
  1338. X    else  {
  1339. X        if(  n  <  BREAK_2  )  {
  1340. X        rand_type = TYPE_1;
  1341. X        rand_deg = DEG_1;
  1342. X        rand_sep = SEP_1;
  1343. X        }
  1344. X        else  {
  1345. X        if(  n  <  BREAK_3  )  {
  1346. X            rand_type = TYPE_2;
  1347. X            rand_deg = DEG_2;
  1348. X            rand_sep = SEP_2;
  1349. X        }
  1350. X        else  {
  1351. X            if(  n  <  BREAK_4  )  {
  1352. X            rand_type = TYPE_3;
  1353. X            rand_deg = DEG_3;
  1354. X            rand_sep = SEP_3;
  1355. X            }
  1356. X            else  {
  1357. X            rand_type = TYPE_4;
  1358. X            rand_deg = DEG_4;
  1359. X            rand_sep = SEP_4;
  1360. X            }
  1361. X        }
  1362. X        }
  1363. X    }
  1364. X    state = &(  ( (long *)arg_state )[1]  );    /* first location */
  1365. X    end_ptr = &state[ rand_deg ];    /* must set end_ptr before srandom */
  1366. X    srandom( seed );
  1367. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  1368. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  1369. X    return( ostate );
  1370. X}
  1371. X
  1372. X
  1373. X
  1374. X/*
  1375. X * setstate:
  1376. X * Restore the state from the given state array.
  1377. X * Note: it is important that we also remember the locations of the pointers
  1378. X * in the current state information, and restore the locations of the pointers
  1379. X * from the old state information.  This is done by multiplexing the pointer
  1380. X * location into the zeroeth word of the state information.
  1381. X * Note that due to the order in which things are done, it is OK to call
  1382. X * setstate() with the same state as the current state.
  1383. X * Returns a pointer to the old state information.
  1384. X */
  1385. X
  1386. Xchar  *
  1387. Xsetstate( arg_state )
  1388. X
  1389. X    char        *arg_state;
  1390. X{
  1391. X    register  long        *new_state    = (long *)arg_state;
  1392. X    register  int        type        = new_state[0]%MAX_TYPES;
  1393. X    register  int        rear        = new_state[0]/MAX_TYPES;
  1394. X    char            *ostate        = (char *)( &state[ -1 ] );
  1395. X
  1396. X    if(  rand_type  ==  TYPE_0  )  state[ -1 ] = rand_type;
  1397. X    else  state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
  1398. X    switch(  type  )  {
  1399. X        case  TYPE_0:
  1400. X        case  TYPE_1:
  1401. X        case  TYPE_2:
  1402. X        case  TYPE_3:
  1403. X        case  TYPE_4:
  1404. X        rand_type = type;
  1405. X        rand_deg = degrees[ type ];
  1406. X        rand_sep = seps[ type ];
  1407. X        break;
  1408. X
  1409. X        default:
  1410. X        fprintf( stderr, "setstate: state info has been munged; not changed.\n" );
  1411. X    }
  1412. X    state = &new_state[ 1 ];
  1413. X    if(  rand_type  !=  TYPE_0  )  {
  1414. X        rptr = &state[ rear ];
  1415. X        fptr = &state[ (rear + rand_sep)%rand_deg ];
  1416. X    }
  1417. X    end_ptr = &state[ rand_deg ];        /* set end_ptr too */
  1418. X    return( ostate );
  1419. X}
  1420. X
  1421. X
  1422. X
  1423. X/*
  1424. X * random:
  1425. X * If we are using the trivial TYPE_0 R.N.G., just do the old linear
  1426. X * congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
  1427. X * same in all ther other cases due to all the global variables that have been
  1428. X * set up.  The basic operation is to add the number at the rear pointer into
  1429. X * the one at the front pointer.  Then both pointers are advanced to the next
  1430. X * location cyclically in the table.  The value returned is the sum generated,
  1431. X * reduced to 31 bits by throwing away the "least random" low bit.
  1432. X * Note: the code takes advantage of the fact that both the front and
  1433. X * rear pointers can't wrap on the same call by not testing the rear
  1434. X * pointer if the front one has wrapped.
  1435. X * Returns a 31-bit random number.
  1436. X */
  1437. X
  1438. Xlong
  1439. Xrandom()
  1440. X{
  1441. X    long        i;
  1442. X    
  1443. X    if(  rand_type  ==  TYPE_0  )  {
  1444. X        i = state[0] = ( state[0]*1103515245 + 12345 )&0x7fffffff;
  1445. X    }
  1446. X    else  {
  1447. X        *fptr += *rptr;
  1448. X        i = (*fptr >> 1)&0x7fffffff;    /* chucking least random bit */
  1449. X        if(  ++fptr  >=  end_ptr  )  {
  1450. X        fptr = state;
  1451. X        ++rptr;
  1452. X        }
  1453. X        else  {
  1454. X        if(  ++rptr  >=  end_ptr  )  rptr = state;
  1455. X        }
  1456. X    }
  1457. X    return( i );
  1458. X}
  1459. X
  1460. END_OF_FILE
  1461. if test 12793 -ne `wc -c <'random.c'`; then
  1462.     echo shar: \"'random.c'\" unpacked with wrong size!
  1463. fi
  1464. # end of 'random.c'
  1465. fi
  1466. if test -f 'strftime.3' -a "${1}" != "-c" ; then 
  1467.   echo shar: Will not clobber existing file \"'strftime.3'\"
  1468. else
  1469. echo shar: Extracting \"'strftime.3'\" \(5331 characters\)
  1470. sed "s/^X//" >'strftime.3' <<'END_OF_FILE'
  1471. X.TH STRFTIME 3
  1472. X.SH NAME
  1473. Xstrftime \- generate formatted time information
  1474. X.SH SYNOPSIS
  1475. X.ft B
  1476. X.nf
  1477. X#include <sys/types.h>
  1478. X#include <time.h>
  1479. X.sp
  1480. Xsize_t strftime(char *s, size_t maxsize, const char *format,
  1481. X    const struct tm *timeptr);
  1482. X.SH DESCRIPTION
  1483. XThe following description is transcribed verbatim from the December 7, 1988
  1484. Xdraft standard for ANSI C.
  1485. XThis draft is essentially identical in technical content
  1486. Xto the final version of the standard.
  1487. X.LP
  1488. XThe
  1489. X.B strftime
  1490. Xfunction places characters into the array pointed to by
  1491. X.B s
  1492. Xas controlled by the string pointed to by
  1493. X.BR format .
  1494. XThe format shall be a multibyte character sequence, beginning and ending in
  1495. Xits initial shift state.
  1496. XThe
  1497. X.B format
  1498. Xstring consists of zero or more conversion specifiers and ordinary
  1499. Xmultibyte characters.  A conversion specifier consists of a
  1500. X.B %
  1501. Xcharacter followed by a character that determines the behavior of the
  1502. Xconversion specifier.
  1503. XAll ordinary multibyte characters (including the terminating null
  1504. Xcharacter) are copied unchanged into the array.
  1505. XIf copying takes place between objects that overlap the behavior is undefined.
  1506. XNo more than
  1507. X.B maxsize
  1508. Xcharacters are placed into the array.
  1509. XEach conversion specifier is replaced by appropriate characters as described
  1510. Xin the following list.
  1511. XThe appropriate characters are determined by the
  1512. X.B LC_TIME
  1513. Xcategory of the current locale and by the values contained in the
  1514. Xstructure pointed to by
  1515. X.BR timeptr .
  1516. X.TP
  1517. X.B %a
  1518. Xis replaced by the locale's abbreviated weekday name.
  1519. X.TP
  1520. X.B %A
  1521. Xis replaced by the locale's full weekday name.
  1522. X.TP
  1523. X.B %b
  1524. Xis replaced by the locale's abbreviated month name.
  1525. X.TP
  1526. X.B %B
  1527. Xis replaced by the locale's full month name.
  1528. X.TP
  1529. X.B %c
  1530. Xis replaced by the locale's appropriate date and time representation.
  1531. X.TP
  1532. X.B %d
  1533. Xis replaced by the day of the month as a decimal number
  1534. X.RB ( 01 - 31 ).
  1535. X.TP
  1536. X.B %H
  1537. Xis replaced by the hour (24-hour clock) as a decimal number
  1538. X.RB ( 00 - 23 ).
  1539. X.TP
  1540. X.B %I
  1541. Xis replaced by the hour (12-hour clock) as a decimal number
  1542. X.RB ( 01 - 12 ).
  1543. X.TP
  1544. X.B %j
  1545. Xis replaced by the day of the year as a decimal number
  1546. X.RB ( 001 - 366 ).
  1547. X.TP
  1548. X.B %m
  1549. Xis replaced by the month as a decimal number
  1550. X.RB ( 01 - 12 ).
  1551. X.TP
  1552. X.B %M
  1553. Xis replaced by the minute as a decimal number
  1554. X.RB ( 00 - 59 ).
  1555. X.TP
  1556. X.B %p
  1557. Xis replaced by the locale's equivalent of the AM/PM designations associated
  1558. Xwith a 12-hour clock.
  1559. X.TP
  1560. X.B %S
  1561. Xis replaced by the second as a decimal number
  1562. X.RB ( 00 - 61 ).
  1563. X.TP
  1564. X.B %U
  1565. Xis replaced by the week number of the year (the first Sunday as the first
  1566. Xday of week 1) as a decimal number
  1567. X.RB ( 00 - 53 ).
  1568. X.TP
  1569. X.B %w
  1570. Xis replaced by the weekday as a decimal number
  1571. X.RB [ "0 " (Sunday)- 6 ].
  1572. X.TP
  1573. X.B %W
  1574. Xis replaced by the week number of the year (the first Monday as the first
  1575. Xday of week 1) as a decimal number
  1576. X.RB ( 00 - 53 ).
  1577. X.TP
  1578. X.B %x
  1579. Xis replaced by the locale's appropriate date representation.
  1580. X.TP
  1581. X.B %X
  1582. Xis replaced by the locale's appropriate time representation.
  1583. X.TP
  1584. X.B %y
  1585. Xis replaced by the year without century as a decimal number
  1586. X.RB ( 00 - 99 ).
  1587. X.TP
  1588. X.B %Y
  1589. Xis replaced by the year with century as a decimal number.
  1590. X.TP
  1591. X.B %Z
  1592. Xis replaced by the time zone name or abbreviation, or by no characters if
  1593. Xno time zone is determinable.
  1594. X.TP
  1595. X.B %%
  1596. Xis replaced by
  1597. X.BR % .
  1598. X.LP
  1599. XIf a conversion specifier is not one of the above, the behavior is
  1600. Xundefined.
  1601. X.SH RETURNS
  1602. XIf the total number of resulting characters including the terminating null
  1603. Xcharacter is not more than
  1604. X.BR maxsize ,
  1605. Xthe
  1606. X.B strftime
  1607. Xfunction returns the number of characters placed into the array pointed to
  1608. Xby
  1609. X.B s
  1610. Xnot including the terminating null character.
  1611. XOtherwise, zero is returned and the contents of the array are indeterminate.
  1612. X.SH NON-ANSI EXTENSIONS
  1613. XIf
  1614. X.B SYSV_EXT
  1615. Xis defined when the routine is compiled, then the following additional
  1616. Xconversions will be available.
  1617. XThese are borrowed from the System V
  1618. X.IR cftime (3)
  1619. Xand
  1620. X.IR ascftime (3)
  1621. Xroutines.
  1622. X.TP
  1623. X.B %D
  1624. Xis equivalent to specifying
  1625. X.BR %m/%d/%y .
  1626. X.TP
  1627. X.B %e
  1628. Xis replaced by the day of the month,
  1629. Xpadded with a blank if it is only one digit.
  1630. X.TP
  1631. X.B %h
  1632. Xis equivalent to
  1633. X.BR %b ,
  1634. Xabove.
  1635. X.TP
  1636. X.B %n
  1637. Xis replaced with a newline character (\s-1ASCII LF\s+1).
  1638. X.TP
  1639. X.B %r
  1640. Xis equivalent to specifying
  1641. X.BR "%I:%M:%S %p" .
  1642. X.TP
  1643. X.B %R
  1644. Xis equivalent to specifying
  1645. X.BR %H:%M: .
  1646. X.TP
  1647. X.B %T
  1648. Xis equivalent to specifying
  1649. X.BR %H:%M:%S .
  1650. X.TP
  1651. X.B %t
  1652. Xis replaced with a \s-1TAB\s+1 character.
  1653. X.SH SEE ALSO
  1654. Xtime(2), ctime(3), localtime(3)
  1655. X.SH BUGS
  1656. XThis version does not handle multibyte characters or pay attention to the
  1657. Xsetting of the
  1658. X.B LC_TIME
  1659. Xenvironment variable.
  1660. X.LP
  1661. XIt is not clear what is ``appropriate'' for the C locale; the values
  1662. Xreturned are a best guess on the author's part.
  1663. X.SH CAVEATS
  1664. XThis implementation calls
  1665. X.IR tzset (3)
  1666. Xexactly once.  If the
  1667. X.B TZ
  1668. Xenvironment variable is changed after
  1669. X.B strftime
  1670. Xhas been called, then
  1671. X.IR tzset (3)
  1672. Xmust be called again, explicitly, in order for the
  1673. Xcorrect timezone information to be available.
  1674. X.SH AUTHOR
  1675. X.nf
  1676. XArnold Robbins
  1677. XAudioFAX, Inc.
  1678. XSuite 200
  1679. X2000 Powers Ferry Road
  1680. XMarietta, GA. 30067
  1681. XU.S.A.
  1682. XINTERNET: arnold@audiofax.com
  1683. XUUCP:     emory!audfax!arnold
  1684. XPhone:    +1 404 933 7600
  1685. XFax-box:  +1 404 618 4581
  1686. X.fi
  1687. X.SH ACKNOWLEDGEMENTS
  1688. XThanks to Geoff Clare <gwc@root.co.uk> for helping debug earlier
  1689. Xversions of this routine.
  1690. XAdditional thanks to Arthur David Olsen <ado@elsie.nci.nih.gov>
  1691. Xfor some code improvements.
  1692. END_OF_FILE
  1693. if test 5331 -ne `wc -c <'strftime.3'`; then
  1694.     echo shar: \"'strftime.3'\" unpacked with wrong size!
  1695. fi
  1696. # end of 'strftime.3'
  1697. fi
  1698. if test -f 'strftime.c' -a "${1}" != "-c" ; then 
  1699.   echo shar: Will not clobber existing file \"'strftime.c'\"
  1700. else
  1701. echo shar: Extracting \"'strftime.c'\" \(6976 characters\)
  1702. sed "s/^X//" >'strftime.c' <<'END_OF_FILE'
  1703. X/*
  1704. X * strftime.c
  1705. X *
  1706. X * Public-domain relatively quick-and-dirty implemenation of
  1707. X * ANSI library routine for System V Unix systems.
  1708. X *
  1709. X * It's written in old-style C for maximal portability.
  1710. X * However, since I'm used to prototypes, I've included them too.
  1711. X *
  1712. X * If you want stuff in the System V ascftime routine, add the SYSV_EXT define.
  1713. X *
  1714. X * The code for %c, %x, and %X is my best guess as to what's "appropriate".
  1715. X * This version ignores LOCALE information.
  1716. X * It also doesn't worry about multi-byte characters.
  1717. X * So there.
  1718. X *
  1719. X * Arnold Robbins
  1720. X * January, February, 1991
  1721. X *
  1722. X * Fixes from ado@elsie.nci.nih.gov
  1723. X * February 1991
  1724. X */
  1725. X
  1726. X#include <stdio.h>
  1727. X#include <string.h>
  1728. X#include <time.h>
  1729. X#include <sys/types.h>
  1730. X
  1731. X#ifndef __STDC__
  1732. X#define const    /**/
  1733. X#endif
  1734. X
  1735. X#ifndef __STDC__
  1736. Xextern void tzset();
  1737. Xextern char *strchr();
  1738. Xstatic int weeknumber();
  1739. X#else
  1740. Xextern void tzset(void);
  1741. Xextern char *strchr(const char *str, int ch);
  1742. Xstatic int weeknumber(const struct tm *timeptr, int firstweekday);
  1743. X#endif
  1744. X
  1745. Xextern char *tzname[2];
  1746. Xextern int daylight;
  1747. X
  1748. X#define SYSV_EXT    1    /* stuff in System V ascftime routine */
  1749. X
  1750. X/* strftime --- produce formatted time */
  1751. X
  1752. X#ifndef __STDC__
  1753. Xsize_t
  1754. Xstrftime(s, maxsize, format, timeptr)
  1755. Xchar *s;
  1756. Xsize_t maxsize;
  1757. Xconst char *format;
  1758. Xconst struct tm *timeptr;
  1759. X#else
  1760. Xsize_t
  1761. Xstrftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
  1762. X#endif
  1763. X{
  1764. X    char *endp = s + maxsize;
  1765. X    char *start = s;
  1766. X    char tbuf[100];
  1767. X    int i;
  1768. X    static short first = 1;
  1769. X
  1770. X    /* various tables, useful in North America */
  1771. X    static char *days_a[] = {
  1772. X        "Sun", "Mon", "Tue", "Wed",
  1773. X        "Thu", "Fri", "Sat",
  1774. X    };
  1775. X    static char *days_l[] = {
  1776. X        "Sunday", "Monday", "Tuesday", "Wednesday",
  1777. X        "Thursday", "Friday", "Saturday",
  1778. X    };
  1779. X    static char *months_a[] = {
  1780. X        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1781. X        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  1782. X    };
  1783. X    static char *months_l[] = {
  1784. X        "January", "February", "March", "April",
  1785. X        "May", "June", "July", "August", "September",
  1786. X        "October", "November", "December",
  1787. X    };
  1788. X    static char *ampm[] = { "AM", "PM", };
  1789. X
  1790. X    if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0)
  1791. X        return 0;
  1792. X
  1793. X    if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize)
  1794. X        return 0;
  1795. X
  1796. X    if (first) {
  1797. X        tzset();
  1798. X        first = 0;
  1799. X    }
  1800. X
  1801. X    for (; *format && s < endp - 1; format++) {
  1802. X        tbuf[0] = '\0';
  1803. X        if (*format != '%') {
  1804. X            *s++ = *format;
  1805. X            continue;
  1806. X        }
  1807. X        switch (*++format) {
  1808. X        case '\0':
  1809. X            *s++ = '%';
  1810. X            goto out;
  1811. X
  1812. X        case '%':
  1813. X            *s++ = '%';
  1814. X            continue;
  1815. X
  1816. X        case 'a':    /* abbreviated weekday name */
  1817. X            if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
  1818. X                strcpy(tbuf, "?");
  1819. X            else
  1820. X                strcpy(tbuf, days_a[timeptr->tm_wday]);
  1821. X            break;
  1822. X
  1823. X        case 'A':    /* full weekday name */
  1824. X            if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
  1825. X                strcpy(tbuf, "?");
  1826. X            else
  1827. X                strcpy(tbuf, days_l[timeptr->tm_wday]);
  1828. X            break;
  1829. X
  1830. X#ifdef SYSV_EXT
  1831. X        case 'h':    /* abbreviated month name */
  1832. X#endif
  1833. X        case 'b':    /* abbreviated month name */
  1834. X            if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
  1835. X                strcpy(tbuf, "?");
  1836. X            else
  1837. X                strcpy(tbuf, months_a[timeptr->tm_mon]);
  1838. X            break;
  1839. X
  1840. X        case 'B':    /* full month name */
  1841. X            if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
  1842. X                strcpy(tbuf, "?");
  1843. X            else
  1844. X                strcpy(tbuf, months_l[timeptr->tm_mon]);
  1845. X            break;
  1846. X
  1847. X        case 'c':    /* appropriate date and time representation */
  1848. X            sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d",
  1849. X                days_a[timeptr->tm_wday],
  1850. X                months_a[timeptr->tm_mon],
  1851. X                timeptr->tm_mday,
  1852. X                timeptr->tm_hour,
  1853. X                timeptr->tm_min,
  1854. X                timeptr->tm_sec,
  1855. X                timeptr->tm_year + 1900);
  1856. X            break;
  1857. X
  1858. X        case 'd':    /* day of the month, 01 - 31 */
  1859. X            sprintf(tbuf, "%02d", timeptr->tm_mday);
  1860. X            break;
  1861. X
  1862. X        case 'H':    /* hour, 24-hour clock, 00 - 23 */
  1863. X            sprintf(tbuf, "%02d", timeptr->tm_hour);
  1864. X            break;
  1865. X
  1866. X        case 'I':    /* hour, 12-hour clock, 01 - 12 */
  1867. X            i = timeptr->tm_hour;
  1868. X            if (i == 0)
  1869. X                i = 12;
  1870. X            else if (i > 12)
  1871. X                i -= 12;
  1872. X            sprintf(tbuf, "%02d", i);
  1873. X            break;
  1874. X
  1875. X        case 'j':    /* day of the year, 001 - 366 */
  1876. X            sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
  1877. X            break;
  1878. X
  1879. X        case 'm':    /* month, 01 - 12 */
  1880. X            sprintf(tbuf, "%02d", timeptr->tm_mon + 1);
  1881. X            break;
  1882. X
  1883. X        case 'M':    /* minute, 00 - 59 */
  1884. X            sprintf(tbuf, "%02d", timeptr->tm_min);
  1885. X            break;
  1886. X
  1887. X        case 'p':    /* am or pm based on 12-hour clock */
  1888. X            if (timeptr->tm_hour < 12)
  1889. X                strcpy(tbuf, ampm[0]);
  1890. X            else
  1891. X                strcpy(tbuf, ampm[1]);
  1892. X            break;
  1893. X
  1894. X        case 'S':    /* second, 00 - 61 */
  1895. X            sprintf(tbuf, "%02d", timeptr->tm_sec);
  1896. X            break;
  1897. X
  1898. X        case 'U':    /* week of year, Sunday is first day of week */
  1899. X            sprintf(tbuf, "%d", weeknumber(timeptr, 0));
  1900. X            break;
  1901. X
  1902. X        case 'w':    /* weekday, Sunday == 0, 0 - 6 */
  1903. X            sprintf(tbuf, "%d", timeptr->tm_wday);
  1904. X            break;
  1905. X
  1906. X        case 'W':    /* week of year, Monday is first day of week */
  1907. X            sprintf(tbuf, "%d", weeknumber(timeptr, 1));
  1908. X            break;
  1909. X
  1910. X        case 'x':    /* appropriate date representation */
  1911. X            sprintf(tbuf, "%s %s %2d %d",
  1912. X                days_a[timeptr->tm_wday],
  1913. X                months_a[timeptr->tm_mon],
  1914. X                timeptr->tm_mday,
  1915. X                timeptr->tm_year + 1900);
  1916. X            break;
  1917. X
  1918. X        case 'X':    /* appropriate time representation */
  1919. X            sprintf(tbuf, "%02d:%02d:%02d",
  1920. X                timeptr->tm_hour,
  1921. X                timeptr->tm_min,
  1922. X                timeptr->tm_sec);
  1923. X            break;
  1924. X
  1925. X        case 'y':    /* year without a century, 00 - 99 */
  1926. X            i = timeptr->tm_year % 100;
  1927. X            sprintf(tbuf, "%d", i);
  1928. X            break;
  1929. X
  1930. X        case 'Y':    /* year with century */
  1931. X            sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
  1932. X            break;
  1933. X
  1934. X        case 'Z':    /* time zone name or abbrevation */
  1935. X            i = 0;
  1936. X            if (daylight && timeptr->tm_isdst)
  1937. X                i = 1;
  1938. X            strcpy(tbuf, tzname[i]);
  1939. X            break;
  1940. X
  1941. X#ifdef SYSV_EXT
  1942. X        case 'n':    /* same as \n */
  1943. X            tbuf[0] = '\n';
  1944. X            tbuf[1] = '\0';
  1945. X            break;
  1946. X
  1947. X        case 't':    /* same as \t */
  1948. X            tbuf[0] = '\t';
  1949. X            tbuf[1] = '\0';
  1950. X            break;
  1951. X
  1952. X        case 'D':    /* date as %m/%d/%y */
  1953. X            strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
  1954. X            break;
  1955. X
  1956. X        case 'e':    /* day of month, blank padded */
  1957. X            sprintf(tbuf, "%2d", timeptr->tm_mday);
  1958. X            break;
  1959. X
  1960. X        case 'r':    /* time as %I:%M:%S %p */
  1961. X            strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);
  1962. X            break;
  1963. X
  1964. X        case 'R':    /* time as %H:%M */
  1965. X            strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);
  1966. X            break;
  1967. X
  1968. X        case 'T':    /* time as %H:%M:%S */
  1969. X            strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
  1970. X            break;
  1971. X#endif
  1972. X
  1973. X        default:
  1974. X            tbuf[0] = '%';
  1975. X            tbuf[1] = *format;
  1976. X            tbuf[2] = '\0';
  1977. X            break;
  1978. X        }
  1979. X        i = strlen(tbuf);
  1980. X        if (i)
  1981. X            if (s + i < endp - 1) {
  1982. X                strcpy(s, tbuf);
  1983. X                s += i;
  1984. X            } else
  1985. X                return 0;
  1986. X    }
  1987. Xout:
  1988. X    if (s < endp && *format == '\0') {
  1989. X        *s = '\0';
  1990. X        return (s - start);
  1991. X    } else
  1992. X        return 0;
  1993. X}
  1994. X
  1995. X/* weeknumber --- figure how many weeks into the year */
  1996. X
  1997. X/* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */
  1998. X
  1999. X#ifndef __STDC__
  2000. Xstatic int
  2001. Xweeknumber(timeptr, firstweekday)
  2002. Xconst struct tm *timeptr;
  2003. Xint firstweekday;
  2004. X#else
  2005. Xstatic int
  2006. Xweeknumber(const struct tm *timeptr, int firstweekday)
  2007. X#endif
  2008. X{
  2009. X    if (firstweekday == 0)
  2010. X        return (timeptr->tm_yday + 7 - timeptr->tm_wday) / 7;
  2011. X    else
  2012. X        return (timeptr->tm_yday + 7 -
  2013. X            (timeptr->tm_wday ? (timeptr->tm_wday - 1) : 6)) / 7;
  2014. X}
  2015. END_OF_FILE
  2016. if test 6976 -ne `wc -c <'strftime.c'`; then
  2017.     echo shar: \"'strftime.c'\" unpacked with wrong size!
  2018. fi
  2019. # end of 'strftime.c'
  2020. fi
  2021. echo shar: End of archive 2 \(of 2\).
  2022. cp /dev/null ark2isdone
  2023. MISSING=""
  2024. for I in 1 2 ; do
  2025.     if test ! -f ark${I}isdone ; then
  2026.     MISSING="${MISSING} ${I}"
  2027.     fi
  2028. done
  2029. if test "${MISSING}" = "" ; then
  2030.     echo You have unpacked both archives.
  2031.     rm -f ark[1-9]isdone
  2032. else
  2033.     echo You still need to unpack the following archives:
  2034.     echo "        " ${MISSING}
  2035. fi
  2036. ##  End of shell archive.
  2037. exit 0
  2038.  
  2039. -- 
  2040. David H. Brierley
  2041. Home: dave@galaxia.newport.ri.us; Work: dhb@quahog.ssd.ray.com
  2042. Send comp.sources.3b1 submissions to comp-sources-3b1@galaxia.newport.ri.us
  2043. %% Can I be excused, my brain is full. **
  2044.