Annotation of 43BSDReno/share/zoneinfo/zic.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: #ifndef NOID
                      3: static char    elsieid[] = "@(#)zic.c  4.12";
                      4: #endif /* !defined NOID */
                      5: #endif /* !defined lint */
                      6: 
                      7: #include "stdio.h"
                      8: #include "tzfile.h"
                      9: #include "ctype.h"
                     10: #include "time.h"
                     11: #include "string.h"
                     12: #include "stdlib.h"
                     13: #include "sys/stat.h"
                     14: #include "nonstd.h"
                     15: 
                     16: #ifndef TRUE
                     17: #define TRUE   1
                     18: #define FALSE  0
                     19: #endif /* !defined TRUE */
                     20: 
                     21: struct rule {
                     22:        const char *    r_filename;
                     23:        int             r_linenum;
                     24:        const char *    r_name;
                     25: 
                     26:        int             r_loyear;       /* for example, 1986 */
                     27:        int             r_hiyear;       /* for example, 1986 */
                     28:        const char *    r_yrtype;
                     29: 
                     30:        int             r_month;        /* 0..11 */
                     31: 
                     32:        int             r_dycode;       /* see below */
                     33:        int             r_dayofmonth;
                     34:        int             r_wday;
                     35: 
                     36:        long            r_tod;          /* time from midnight */
                     37:        int             r_todisstd;     /* above is standard time if TRUE */
                     38:                                        /* or wall clock time if FALSE */
                     39:        long            r_stdoff;       /* offset from standard time */
                     40:        const char *    r_abbrvar;      /* variable part of abbreviation */
                     41: 
                     42:        int             r_todo;         /* a rule to do (used in outzone) */
                     43:        time_t          r_temp;         /* used in outzone */
                     44: };
                     45: 
                     46: /*
                     47: **     r_dycode                r_dayofmonth    r_wday
                     48: */
                     49: 
                     50: #define DC_DOM         0       /* 1..31 */     /* unused */
                     51: #define DC_DOWGEQ      1       /* 1..31 */     /* 0..6 (Sun..Sat) */
                     52: #define DC_DOWLEQ      2       /* 1..31 */     /* 0..6 (Sun..Sat) */
                     53: 
                     54: struct zone {
                     55:        const char *    z_filename;
                     56:        int             z_linenum;
                     57: 
                     58:        const char *    z_name;
                     59:        long            z_gmtoff;
                     60:        const char *    z_rule;
                     61:        const char *    z_format;
                     62: 
                     63:        long            z_stdoff;
                     64: 
                     65:        struct rule *   z_rules;
                     66:        int             z_nrules;
                     67: 
                     68:        struct rule     z_untilrule;
                     69:        time_t          z_untiltime;
                     70: };
                     71: 
                     72: extern int     emkdir P((const char * name, int mode));
                     73: extern int     getopt P((int argc, char * argv[], const char * options));
                     74: extern char *  icatalloc P((char * old, const char * new));
                     75: extern char *  icpyalloc P((const char * string));
                     76: extern void    ifree P((char * p));
                     77: extern char *  imalloc P((int n));
                     78: extern char *  irealloc P((char * old, int n));
                     79: extern int     link P((const char * fromname, const char * toname));
                     80: extern char *  optarg;
                     81: extern int     optind;
                     82: extern void    perror P((const char * string));
                     83: extern char *  scheck P((const char * string, const char * format));
                     84: 
                     85: static void    addtt P((time_t starttime, int type));
                     86: static int     addtype P((long gmtoff, const char * abbr, int isdst,
                     87:     int ttisstd));
                     88: static void    addleap P((time_t t, int positive, int rolling));
                     89: static void    adjleap P((void));
                     90: static void    associate P((void));
                     91: static int     ciequal P((const char * ap, const char * bp));
                     92: static void    convert P((long val, char * buf));
                     93: static void    dolink P((const char * fromfile, const char * tofile));
                     94: static void    eat P((const char * name, int num));
                     95: static void    eats P((const char * name, int num,
                     96:                        const char * rname, int rnum));
                     97: static long    eitol P((int i));
                     98: static void    error P((const char * message));
                     99: static char ** getfields P((char * buf));
                    100: static long    gethms P((const char * string, const char * errstrng,
                    101:                        int signable));
                    102: static void    infile P((const char * filename));
                    103: static void    inleap P((char ** fields, int nfields));
                    104: static void    inlink P((char ** fields, int nfields));
                    105: static void    inrule P((char ** fields, int nfields));
                    106: static int     inzcont P((char ** fields, int nfields));
                    107: static int     inzone P((char ** fields, int nfields));
                    108: static int     inzsub P((char ** fields, int nfields, int iscont));
                    109: static int     itsabbr P((const char * abbr, const char * word));
                    110: static int     itsdir P((const char * name));
                    111: static int     lowerit P((int c));
                    112: static char *  memcheck P((char * tocheck));
                    113: static int     mkdirs P((char * filename));
                    114: static void    newabbr P((const char * abbr));
                    115: static long    oadd P((long t1, long t2));
                    116: static void    outzone P((const struct zone * zp, int ntzones));
                    117: static void    puttzcode P((long code, FILE * fp));
                    118: static int     rcomp P((const genericptr_t leftp, const genericptr_t rightp));
                    119: static time_t  rpytime P((const struct rule * rp, int wantedy));
                    120: static void    rulesub P((struct rule * rp,
                    121:                        char * loyearp, char * hiyearp,
                    122:                        char * typep, char * monthp,
                    123:                        char * dayp, char * timep));
                    124: static void    setboundaries P((void));
                    125: static time_t  tadd P((time_t t1, long t2));
                    126: static void    usage P((void));
                    127: static void    writezone P((const char * name));
                    128: static int     yearistype P((int year, const char * type));
                    129: 
                    130: static int             charcnt;
                    131: static int             errors;
                    132: static const char *    filename;
                    133: static int             leapcnt;
                    134: static int             linenum;
                    135: static time_t          max_time;
                    136: static int             max_year;
                    137: static time_t          min_time;
                    138: static int             min_year;
                    139: static int             noise;
                    140: static const char *    rfilename;
                    141: static int             rlinenum;
                    142: static const char *    progname;
                    143: static int             timecnt;
                    144: static int             typecnt;
                    145: static int             tt_signed;
                    146: 
                    147: /*
                    148: ** Line codes.
                    149: */
                    150: 
                    151: #define LC_RULE                0
                    152: #define LC_ZONE                1
                    153: #define LC_LINK                2
                    154: #define LC_LEAP                3
                    155: 
                    156: /*
                    157: ** Which fields are which on a Zone line.
                    158: */
                    159: 
                    160: #define ZF_NAME                1
                    161: #define ZF_GMTOFF      2
                    162: #define ZF_RULE                3
                    163: #define ZF_FORMAT      4
                    164: #define ZF_TILYEAR     5
                    165: #define ZF_TILMONTH    6
                    166: #define ZF_TILDAY      7
                    167: #define ZF_TILTIME     8
                    168: #define ZONE_MINFIELDS 5
                    169: #define ZONE_MAXFIELDS 9
                    170: 
                    171: /*
                    172: ** Which fields are which on a Zone continuation line.
                    173: */
                    174: 
                    175: #define ZFC_GMTOFF     0
                    176: #define ZFC_RULE       1
                    177: #define ZFC_FORMAT     2
                    178: #define ZFC_TILYEAR    3
                    179: #define ZFC_TILMONTH   4
                    180: #define ZFC_TILDAY     5
                    181: #define ZFC_TILTIME    6
                    182: #define ZONEC_MINFIELDS        3
                    183: #define ZONEC_MAXFIELDS        7
                    184: 
                    185: /*
                    186: ** Which files are which on a Rule line.
                    187: */
                    188: 
                    189: #define RF_NAME                1
                    190: #define RF_LOYEAR      2
                    191: #define RF_HIYEAR      3
                    192: #define RF_COMMAND     4
                    193: #define RF_MONTH       5
                    194: #define RF_DAY         6
                    195: #define RF_TOD         7
                    196: #define RF_STDOFF      8
                    197: #define RF_ABBRVAR     9
                    198: #define RULE_FIELDS    10
                    199: 
                    200: /*
                    201: ** Which fields are which on a Link line.
                    202: */
                    203: 
                    204: #define LF_FROM                1
                    205: #define LF_TO          2
                    206: #define LINK_FIELDS    3
                    207: 
                    208: /*
                    209: ** Which fields are which on a Leap line.
                    210: */
                    211: 
                    212: #define LP_YEAR                1
                    213: #define LP_MONTH       2
                    214: #define LP_DAY         3
                    215: #define LP_TIME                4
                    216: #define LP_CORR                5
                    217: #define LP_ROLL                6
                    218: #define LEAP_FIELDS    7
                    219: 
                    220: /*
                    221: ** Year synonyms.
                    222: */
                    223: 
                    224: #define YR_MINIMUM     0
                    225: #define YR_MAXIMUM     1
                    226: #define YR_ONLY                2
                    227: 
                    228: static struct rule *   rules;
                    229: static int             nrules; /* number of rules */
                    230: 
                    231: static struct zone *   zones;
                    232: static int             nzones; /* number of zones */
                    233: 
                    234: struct link {
                    235:        const char *    l_filename;
                    236:        int             l_linenum;
                    237:        const char *    l_from;
                    238:        const char *    l_to;
                    239: };
                    240: 
                    241: static struct link *   links;
                    242: static int             nlinks;
                    243: 
                    244: struct lookup {
                    245:        const char *    l_word;
                    246:        const int       l_value;
                    247: };
                    248: 
                    249: static struct lookup const *   byword P((const char * string,
                    250:                                        const struct lookup * lp));
                    251: 
                    252: static struct lookup const     line_codes[] = {
                    253:        "Rule",         LC_RULE,
                    254:        "Zone",         LC_ZONE,
                    255:        "Link",         LC_LINK,
                    256:        "Leap",         LC_LEAP,
                    257:        NULL,           0
                    258: };
                    259: 
                    260: static struct lookup const     mon_names[] = {
                    261:        "January",      TM_JANUARY,
                    262:        "February",     TM_FEBRUARY,
                    263:        "March",        TM_MARCH,
                    264:        "April",        TM_APRIL,
                    265:        "May",          TM_MAY,
                    266:        "June",         TM_JUNE,
                    267:        "July",         TM_JULY,
                    268:        "August",       TM_AUGUST,
                    269:        "September",    TM_SEPTEMBER,
                    270:        "October",      TM_OCTOBER,
                    271:        "November",     TM_NOVEMBER,
                    272:        "December",     TM_DECEMBER,
                    273:        NULL,           0
                    274: };
                    275: 
                    276: static struct lookup const     wday_names[] = {
                    277:        "Sunday",       TM_SUNDAY,
                    278:        "Monday",       TM_MONDAY,
                    279:        "Tuesday",      TM_TUESDAY,
                    280:        "Wednesday",    TM_WEDNESDAY,
                    281:        "Thursday",     TM_THURSDAY,
                    282:        "Friday",       TM_FRIDAY,
                    283:        "Saturday",     TM_SATURDAY,
                    284:        NULL,           0
                    285: };
                    286: 
                    287: static struct lookup const     lasts[] = {
                    288:        "last-Sunday",          TM_SUNDAY,
                    289:        "last-Monday",          TM_MONDAY,
                    290:        "last-Tuesday",         TM_TUESDAY,
                    291:        "last-Wednesday",       TM_WEDNESDAY,
                    292:        "last-Thursday",        TM_THURSDAY,
                    293:        "last-Friday",          TM_FRIDAY,
                    294:        "last-Saturday",        TM_SATURDAY,
                    295:        NULL,                   0
                    296: };
                    297: 
                    298: static struct lookup const     begin_years[] = {
                    299:        "minimum",              YR_MINIMUM,
                    300:        "maximum",              YR_MAXIMUM,
                    301:        NULL,                   0
                    302: };
                    303: 
                    304: static struct lookup const     end_years[] = {
                    305:        "minimum",              YR_MINIMUM,
                    306:        "maximum",              YR_MAXIMUM,
                    307:        "only",                 YR_ONLY,
                    308:        NULL,                   0
                    309: };
                    310: 
                    311: static struct lookup const     leap_types[] = {
                    312:        "Rolling",              TRUE,
                    313:        "Stationary",           FALSE,
                    314:        NULL,                   0
                    315: };
                    316: 
                    317: static const int       len_months[2][MONSPERYEAR] = {
                    318:        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
                    319:        31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
                    320: };
                    321: 
                    322: static const int       len_years[2] = {
                    323:        DAYSPERNYEAR, DAYSPERLYEAR
                    324: };
                    325: 
                    326: static time_t          ats[TZ_MAX_TIMES];
                    327: static unsigned char   types[TZ_MAX_TIMES];
                    328: static long            gmtoffs[TZ_MAX_TYPES];
                    329: static char            isdsts[TZ_MAX_TYPES];
                    330: static char            abbrinds[TZ_MAX_TYPES];
                    331: static char            ttisstds[TZ_MAX_TYPES];
                    332: static char            chars[TZ_MAX_CHARS];
                    333: static time_t          trans[TZ_MAX_LEAPS];
                    334: static long            corr[TZ_MAX_LEAPS];
                    335: static char            roll[TZ_MAX_LEAPS];
                    336: 
                    337: /*
                    338: ** Memory allocation.
                    339: */
                    340: 
                    341: static char *
                    342: memcheck(ptr)
                    343: char * const   ptr;
                    344: {
                    345:        if (ptr == NULL) {
                    346:                (void) perror(progname);
                    347:                (void) exit(EXIT_FAILURE);
                    348:        }
                    349:        return ptr;
                    350: }
                    351: 
                    352: #define emalloc(size)          memcheck(imalloc(size))
                    353: #define erealloc(ptr, size)    memcheck(irealloc(ptr, size))
                    354: #define ecpyalloc(ptr)         memcheck(icpyalloc(ptr))
                    355: #define ecatalloc(oldp, newp)  memcheck(icatalloc(oldp, newp))
                    356: 
                    357: /*
                    358: ** Error handling.
                    359: */
                    360: 
                    361: static void
                    362: eats(name, num, rname, rnum)
                    363: const char * const     name;
                    364: const int              num;
                    365: const char * const     rname;
                    366: const int              rnum;
                    367: {
                    368:        filename = name;
                    369:        linenum = num;
                    370:        rfilename = rname;
                    371:        rlinenum = rnum;
                    372: }
                    373: 
                    374: static void
                    375: eat(name, num)
                    376: const char * const     name;
                    377: const int              num;
                    378: {
                    379:        eats(name, num, (char *) NULL, -1);
                    380: }
                    381: 
                    382: static void
                    383: error(string)
                    384: const char * const     string;
                    385: {
                    386:        /*
                    387:        ** Match the format of "cc" to allow sh users to
                    388:        **      zic ... 2>&1 | error -t "*" -v
                    389:        ** on BSD systems.
                    390:        */
                    391:        (void) fprintf(stderr, "\"%s\", line %d: %s",
                    392:                filename, linenum, string);
                    393:        if (rfilename != NULL)
                    394:                (void) fprintf(stderr, " (rule from \"%s\", line %d)",
                    395:                        rfilename, rlinenum);
                    396:        (void) fprintf(stderr, "\n");
                    397:        ++errors;
                    398: }
                    399: 
                    400: static void
                    401: usage()
                    402: {
                    403:        (void) fprintf(stderr,
                    404: "%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\
                    405: \t[ -L leapseconds ] [ filename ... ]\n",
                    406:                progname, progname);
                    407:        (void) exit(EXIT_FAILURE);
                    408: }
                    409: 
                    410: static const char *    psxrules = NULL;
                    411: static const char *    lcltime = NULL;
                    412: static const char *    directory = NULL;
                    413: static const char *    leapsec = NULL;
                    414: static int             sflag = FALSE;
                    415: 
                    416: int
                    417: main(argc, argv)
                    418: int    argc;
                    419: char * argv[];
                    420: {
                    421:        register int    i, j;
                    422:        register int    c;
                    423: 
                    424: #ifdef unix
                    425:        (void) umask(umask(022) | 022);
                    426: #endif /* defined unix */
                    427:        progname = argv[0];
                    428:        while ((c = getopt(argc, argv, "d:l:p:L:vs")) != EOF)
                    429:                switch (c) {
                    430:                        default:
                    431:                                usage();
                    432:                        case 'd':
                    433:                                if (directory == NULL)
                    434:                                        directory = optarg;
                    435:                                else {
                    436:                                        (void) fprintf(stderr,
                    437: "%s: More than one -d option specified\n",
                    438:                                                progname);
                    439:                                        (void) exit(EXIT_FAILURE);
                    440:                                }
                    441:                                break;
                    442:                        case 'l':
                    443:                                if (lcltime == NULL)
                    444:                                        lcltime = optarg;
                    445:                                else {
                    446:                                        (void) fprintf(stderr,
                    447: "%s: More than one -l option specified\n",
                    448:                                                progname);
                    449:                                        (void) exit(EXIT_FAILURE);
                    450:                                }
                    451:                                break;
                    452:                        case 'p':
                    453:                                if (psxrules == NULL)
                    454:                                        psxrules = optarg;
                    455:                                else {
                    456:                                        (void) fprintf(stderr,
                    457: "%s: More than one -p option specified\n",
                    458:                                                progname);
                    459:                                        (void) exit(EXIT_FAILURE);
                    460:                                }
                    461:                                break;
                    462:                        case 'L':
                    463:                                if (leapsec == NULL)
                    464:                                        leapsec = optarg;
                    465:                                else {
                    466:                                        (void) fprintf(stderr,
                    467: "%s: More than one -L option specified\n",
                    468:                                                progname);
                    469:                                        (void) exit(EXIT_FAILURE);
                    470:                                }
                    471:                                break;
                    472:                        case 'v':
                    473:                                noise = TRUE;
                    474:                                break;
                    475:                        case 's':
                    476:                                sflag = TRUE;
                    477:                                break;
                    478:                }
                    479:        if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
                    480:                usage();        /* usage message by request */
                    481:        if (directory == NULL)
                    482:                directory = TZDIR;
                    483: 
                    484:        setboundaries();
                    485: 
                    486:        if (optind < argc && leapsec != NULL) {
                    487:                infile(leapsec);
                    488:                adjleap();
                    489:        }
                    490: 
                    491:        zones = (struct zone *) emalloc(0);
                    492:        rules = (struct rule *) emalloc(0);
                    493:        links = (struct link *) emalloc(0);
                    494:        for (i = optind; i < argc; ++i)
                    495:                infile(argv[i]);
                    496:        if (errors)
                    497:                (void) exit(EXIT_FAILURE);
                    498:        associate();
                    499:        for (i = 0; i < nzones; i = j) {
                    500:                /*
                    501:                ** Find the next non-continuation zone entry.
                    502:                */
                    503:                for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
                    504:                        ;
                    505:                outzone(&zones[i], j - i);
                    506:        }
                    507:        /*
                    508:        ** Make links.
                    509:        */
                    510:        for (i = 0; i < nlinks; ++i)
                    511:                dolink(links[i].l_from, links[i].l_to);
                    512:        if (lcltime != NULL)
                    513:                dolink(lcltime, TZDEFAULT);
                    514:        if (psxrules != NULL)
                    515:                dolink(psxrules, TZDEFRULES);
                    516:        return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
                    517: }
                    518: 
                    519: static void
                    520: dolink(fromfile, tofile)
                    521: const char * const     fromfile;
                    522: const char * const     tofile;
                    523: {
                    524:        register char * fromname;
                    525:        register char * toname;
                    526: 
                    527:        fromname = ecpyalloc(directory);
                    528:        fromname = ecatalloc(fromname, "/");
                    529:        fromname = ecatalloc(fromname, fromfile);
                    530:        toname = ecpyalloc(directory);
                    531:        toname = ecatalloc(toname, "/");
                    532:        toname = ecatalloc(toname, tofile);
                    533:        /*
                    534:        ** We get to be careful here since
                    535:        ** there's a fair chance of root running us.
                    536:        */
                    537:        if (!itsdir(toname))
                    538:                (void) remove(toname);
                    539:        if (link(fromname, toname) != 0) {
                    540:                (void) fprintf(stderr, "%s: Can't link from %s to ",
                    541:                        progname, fromname);
                    542:                (void) perror(toname);
                    543:                (void) exit(EXIT_FAILURE);
                    544:        }
                    545:        ifree(fromname);
                    546:        ifree(toname);
                    547: }
                    548: 
                    549: static void
                    550: setboundaries()
                    551: {
                    552:        register time_t bit;
                    553: 
                    554:        for (bit = 1; bit > 0; bit <<= 1)
                    555:                ;
                    556:        if (bit == 0) {         /* time_t is an unsigned type */
                    557:                tt_signed = FALSE;
                    558:                min_time = 0;
                    559:                max_time = ~(time_t) 0;
                    560:                if (sflag)
                    561:                        max_time >>= 1;
                    562:        } else {
                    563:                tt_signed = TRUE;
                    564:                min_time = bit;
                    565:                max_time = bit;
                    566:                ++max_time;
                    567:                max_time = -max_time;
                    568:                if (sflag)
                    569:                        min_time = 0;
                    570:        }
                    571:        min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
                    572:        max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
                    573: }
                    574: 
                    575: static int
                    576: itsdir(name)
                    577: const char * const     name;
                    578: {
                    579:        struct stat     s;
                    580: 
                    581:        return stat(name, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR;
                    582: }
                    583: 
                    584: /*
                    585: ** Associate sets of rules with zones.
                    586: */
                    587: 
                    588: /*
                    589: ** Sort by rule name.
                    590: */
                    591: 
                    592: static int
                    593: rcomp(cp1, cp2)
                    594: const genericptr_t     cp1;
                    595: const genericptr_t     cp2;
                    596: {
                    597:        return strcmp(((struct rule *) cp1)->r_name,
                    598:                ((struct rule *) cp2)->r_name);
                    599: }
                    600: 
                    601: static void
                    602: associate()
                    603: {
                    604:        register struct zone *  zp;
                    605:        register struct rule *  rp;
                    606:        register int            base, out;
                    607:        register int            i;
                    608: 
                    609:        if (nrules != 0)
                    610:                (void) qsort((genericptr_t) rules,
                    611:                        (qsort_size_t) nrules,
                    612:                        (qsort_size_t) sizeof *rules, rcomp);
                    613:        for (i = 0; i < nzones; ++i) {
                    614:                zp = &zones[i];
                    615:                zp->z_rules = NULL;
                    616:                zp->z_nrules = 0;
                    617:        }
                    618:        for (base = 0; base < nrules; base = out) {
                    619:                rp = &rules[base];
                    620:                for (out = base + 1; out < nrules; ++out)
                    621:                        if (strcmp(rp->r_name, rules[out].r_name) != 0)
                    622:                                break;
                    623:                for (i = 0; i < nzones; ++i) {
                    624:                        zp = &zones[i];
                    625:                        if (strcmp(zp->z_rule, rp->r_name) != 0)
                    626:                                continue;
                    627:                        zp->z_rules = rp;
                    628:                        zp->z_nrules = out - base;
                    629:                }
                    630:        }
                    631:        for (i = 0; i < nzones; ++i) {
                    632:                zp = &zones[i];
                    633:                if (zp->z_nrules == 0) {
                    634:                        /*
                    635:                        ** Maybe we have a local standard time offset.
                    636:                        */
                    637:                        eat(zp->z_filename, zp->z_linenum);
                    638:                        zp->z_stdoff = gethms(zp->z_rule, "unruly zone", TRUE);
                    639:                        /*
                    640:                        ** Note, though, that if there's no rule,
                    641:                        ** a '%s' in the format is a bad thing.
                    642:                        */
                    643:                        if (strchr(zp->z_format, '%') != 0)
                    644:                                error("%s in ruleless zone");
                    645:                }
                    646:        }
                    647:        if (errors)
                    648:                (void) exit(EXIT_FAILURE);
                    649: }
                    650: 
                    651: static void
                    652: infile(name)
                    653: const char *   name;
                    654: {
                    655:        register FILE *                 fp;
                    656:        register char **                fields;
                    657:        register char *                 cp;
                    658:        register const struct lookup *  lp;
                    659:        register int                    nfields;
                    660:        register int                    wantcont;
                    661:        register int                    num;
                    662:        char                            buf[BUFSIZ];
                    663: 
                    664:        if (strcmp(name, "-") == 0) {
                    665:                name = "standard input";
                    666:                fp = stdin;
                    667:        } else if ((fp = fopen(name, "r")) == NULL) {
                    668:                (void) fprintf(stderr, "%s: Can't open ", progname);
                    669:                (void) perror(name);
                    670:                (void) exit(EXIT_FAILURE);
                    671:        }
                    672:        wantcont = FALSE;
                    673:        for (num = 1; ; ++num) {
                    674:                eat(name, num);
                    675:                if (fgets(buf, (int) sizeof buf, fp) != buf)
                    676:                        break;
                    677:                cp = strchr(buf, '\n');
                    678:                if (cp == NULL) {
                    679:                        error("line too long");
                    680:                        (void) exit(EXIT_FAILURE);
                    681:                }
                    682:                *cp = '\0';
                    683:                fields = getfields(buf);
                    684:                nfields = 0;
                    685:                while (fields[nfields] != NULL) {
                    686:                        if (ciequal(fields[nfields], "-"))
                    687:                                fields[nfields] = "";
                    688:                        ++nfields;
                    689:                }
                    690:                if (nfields == 0) {
                    691:                        /* nothing to do */
                    692:                } else if (wantcont) {
                    693:                        wantcont = inzcont(fields, nfields);
                    694:                } else {
                    695:                        lp = byword(fields[0], line_codes);
                    696:                        if (lp == NULL)
                    697:                                error("input line of unknown type");
                    698:                        else switch ((int) (lp->l_value)) {
                    699:                                case LC_RULE:
                    700:                                        inrule(fields, nfields);
                    701:                                        wantcont = FALSE;
                    702:                                        break;
                    703:                                case LC_ZONE:
                    704:                                        wantcont = inzone(fields, nfields);
                    705:                                        break;
                    706:                                case LC_LINK:
                    707:                                        inlink(fields, nfields);
                    708:                                        wantcont = FALSE;
                    709:                                        break;
                    710:                                case LC_LEAP:
                    711:                                        if (name != leapsec)
                    712:                                                (void) fprintf(stderr,
                    713: "%s: Leap line in non leap seconds file %s\n",
                    714:                                                        progname, name);
                    715:                                        else    inleap(fields, nfields);
                    716:                                        wantcont = FALSE;
                    717:                                        break;
                    718:                                default:        /* "cannot happen" */
                    719:                                        (void) fprintf(stderr,
                    720: "%s: panic: Invalid l_value %d\n",
                    721:                                                progname, lp->l_value);
                    722:                                        (void) exit(EXIT_FAILURE);
                    723:                        }
                    724:                }
                    725:                ifree((char *) fields);
                    726:        }
                    727:        if (ferror(fp)) {
                    728:                (void) fprintf(stderr, "%s: Error reading ", progname);
                    729:                (void) perror(filename);
                    730:                (void) exit(EXIT_FAILURE);
                    731:        }
                    732:        if (fp != stdin && fclose(fp)) {
                    733:                (void) fprintf(stderr, "%s: Error closing ", progname);
                    734:                (void) perror(filename);
                    735:                (void) exit(EXIT_FAILURE);
                    736:        }
                    737:        if (wantcont)
                    738:                error("expected continuation line not found");
                    739: }
                    740: 
                    741: /*
                    742: ** Convert a string of one of the forms
                    743: **     h       -h      hh:mm   -hh:mm  hh:mm:ss        -hh:mm:ss
                    744: ** into a number of seconds.
                    745: ** A null string maps to zero.
                    746: ** Call error with errstring and return zero on errors.
                    747: */
                    748: 
                    749: static long
                    750: gethms(string, errstring, signable)
                    751: const char *           string;
                    752: const char * const     errstring;
                    753: const int              signable;
                    754: {
                    755:        int     hh, mm, ss, sign;
                    756: 
                    757:        if (string == NULL || *string == '\0')
                    758:                return 0;
                    759:        if (!signable)
                    760:                sign = 1;
                    761:        else if (*string == '-') {
                    762:                sign = -1;
                    763:                ++string;
                    764:        } else  sign = 1;
                    765:        if (sscanf(string, scheck(string, "%d"), &hh) == 1)
                    766:                mm = ss = 0;
                    767:        else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
                    768:                ss = 0;
                    769:        else if (sscanf(string, scheck(string, "%d:%d:%d"),
                    770:                &hh, &mm, &ss) != 3) {
                    771:                        error(errstring);
                    772:                        return 0;
                    773:        }
                    774:        if (hh < 0 || hh >= HOURSPERDAY ||
                    775:                mm < 0 || mm >= MINSPERHOUR ||
                    776:                ss < 0 || ss > SECSPERMIN) {
                    777:                        error(errstring);
                    778:                        return 0;
                    779:        }
                    780:        return eitol(sign) *
                    781:                (eitol(hh * MINSPERHOUR + mm) *
                    782:                eitol(SECSPERMIN) + eitol(ss));
                    783: }
                    784: 
                    785: static void
                    786: inrule(fields, nfields)
                    787: register char ** const fields;
                    788: const int              nfields;
                    789: {
                    790:        static struct rule      r;
                    791: 
                    792:        if (nfields != RULE_FIELDS) {
                    793:                error("wrong number of fields on Rule line");
                    794:                return;
                    795:        }
                    796:        if (*fields[RF_NAME] == '\0') {
                    797:                error("nameless rule");
                    798:                return;
                    799:        }
                    800:        r.r_filename = filename;
                    801:        r.r_linenum = linenum;
                    802:        r.r_stdoff = gethms(fields[RF_STDOFF], "invalid saved time", TRUE);
                    803:        rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
                    804:                fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
                    805:        r.r_name = ecpyalloc(fields[RF_NAME]);
                    806:        r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
                    807:        rules = (struct rule *) erealloc((char *) rules,
                    808:                (int) ((nrules + 1) * sizeof *rules));
                    809:        rules[nrules++] = r;
                    810: }
                    811: 
                    812: static int
                    813: inzone(fields, nfields)
                    814: register char ** const fields;
                    815: const int              nfields;
                    816: {
                    817:        register int    i;
                    818:        char            buf[132];
                    819: 
                    820:        if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
                    821:                error("wrong number of fields on Zone line");
                    822:                return FALSE;
                    823:        }
                    824:        if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
                    825:                (void) sprintf(buf,
                    826:                        "\"Zone %s\" line and -l option are mutually exclusive",
                    827:                        TZDEFAULT);
                    828:                error(buf);
                    829:                return FALSE;
                    830:        }
                    831:        if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
                    832:                (void) sprintf(buf,
                    833:                        "\"Zone %s\" line and -p option are mutually exclusive",
                    834:                        TZDEFRULES);
                    835:                error(buf);
                    836:                return FALSE;
                    837:        }
                    838:        for (i = 0; i < nzones; ++i)
                    839:                if (zones[i].z_name != NULL &&
                    840:                        strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
                    841:                                (void) sprintf(buf,
                    842: "duplicate zone name %s (file \"%s\", line %d)",
                    843:                                        fields[ZF_NAME],
                    844:                                        zones[i].z_filename,
                    845:                                        zones[i].z_linenum);
                    846:                                error(buf);
                    847:                                return FALSE;
                    848:                }
                    849:        return inzsub(fields, nfields, FALSE);
                    850: }
                    851: 
                    852: static int
                    853: inzcont(fields, nfields)
                    854: register char ** const fields;
                    855: const int              nfields;
                    856: {
                    857:        if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
                    858:                error("wrong number of fields on Zone continuation line");
                    859:                return FALSE;
                    860:        }
                    861:        return inzsub(fields, nfields, TRUE);
                    862: }
                    863: 
                    864: static int
                    865: inzsub(fields, nfields, iscont)
                    866: register char ** const fields;
                    867: const int              nfields;
                    868: const int              iscont;
                    869: {
                    870:        register char *         cp;
                    871:        static struct zone      z;
                    872:        register int            i_gmtoff, i_rule, i_format;
                    873:        register int            i_untilyear, i_untilmonth;
                    874:        register int            i_untilday, i_untiltime;
                    875:        register int            hasuntil;
                    876: 
                    877:        if (iscont) {
                    878:                i_gmtoff = ZFC_GMTOFF;
                    879:                i_rule = ZFC_RULE;
                    880:                i_format = ZFC_FORMAT;
                    881:                i_untilyear = ZFC_TILYEAR;
                    882:                i_untilmonth = ZFC_TILMONTH;
                    883:                i_untilday = ZFC_TILDAY;
                    884:                i_untiltime = ZFC_TILTIME;
                    885:                z.z_name = NULL;
                    886:        } else {
                    887:                i_gmtoff = ZF_GMTOFF;
                    888:                i_rule = ZF_RULE;
                    889:                i_format = ZF_FORMAT;
                    890:                i_untilyear = ZF_TILYEAR;
                    891:                i_untilmonth = ZF_TILMONTH;
                    892:                i_untilday = ZF_TILDAY;
                    893:                i_untiltime = ZF_TILTIME;
                    894:                z.z_name = ecpyalloc(fields[ZF_NAME]);
                    895:        }
                    896:        z.z_filename = filename;
                    897:        z.z_linenum = linenum;
                    898:        z.z_gmtoff = gethms(fields[i_gmtoff], "invalid GMT offset", TRUE);
                    899:        if ((cp = strchr(fields[i_format], '%')) != 0) {
                    900:                if (*++cp != 's' || strchr(cp, '%') != 0) {
                    901:                        error("invalid abbreviation format");
                    902:                        return FALSE;
                    903:                }
                    904:        }
                    905:        z.z_rule = ecpyalloc(fields[i_rule]);
                    906:        z.z_format = ecpyalloc(fields[i_format]);
                    907:        hasuntil = nfields > i_untilyear;
                    908:        if (hasuntil) {
                    909:                z.z_untilrule.r_filename = filename;
                    910:                z.z_untilrule.r_linenum = linenum;
                    911:                rulesub(&z.z_untilrule,
                    912:                        fields[i_untilyear],
                    913:                        "only",
                    914:                        "",
                    915:                        (nfields > i_untilmonth) ? fields[i_untilmonth] : "Jan",
                    916:                        (nfields > i_untilday) ? fields[i_untilday] : "1",
                    917:                        (nfields > i_untiltime) ? fields[i_untiltime] : "0");
                    918:                z.z_untiltime = rpytime(&z.z_untilrule, z.z_untilrule.r_loyear);
                    919:                if (iscont && nzones > 0 && z.z_untiltime < max_time &&
                    920:                        z.z_untiltime > min_time &&
                    921:                        zones[nzones - 1].z_untiltime >= z.z_untiltime) {
                    922: error("Zone continuation line end time is not after end time of previous line");
                    923:                        return FALSE;
                    924:                }
                    925:        }
                    926:        zones = (struct zone *) erealloc((char *) zones,
                    927:                (int) ((nzones + 1) * sizeof *zones));
                    928:        zones[nzones++] = z;
                    929:        /*
                    930:        ** If there was an UNTIL field on this line,
                    931:        ** there's more information about the zone on the next line.
                    932:        */
                    933:        return hasuntil;
                    934: }
                    935: 
                    936: static void
                    937: inleap(fields, nfields)
                    938: register char ** const fields;
                    939: const int              nfields;
                    940: {
                    941:        register const char *           cp;
                    942:        register const struct lookup *  lp;
                    943:        register int                    i, j;
                    944:        int                             year, month, day;
                    945:        long                            dayoff, tod;
                    946:        time_t                          t;
                    947: 
                    948:        if (nfields != LEAP_FIELDS) {
                    949:                error("wrong number of fields on Leap line");
                    950:                return;
                    951:        }
                    952:        dayoff = 0;
                    953:        cp = fields[LP_YEAR];
                    954:        if (sscanf(cp, scheck(cp, "%d"), &year) != 1 ||
                    955:                year < min_year || year > max_year) {
                    956:                        /*
                    957:                         * Leapin' Lizards!
                    958:                         */
                    959:                        error("invalid leaping year");
                    960:                        return;
                    961:        }
                    962:        j = EPOCH_YEAR;
                    963:        while (j != year) {
                    964:                if (year > j) {
                    965:                        i = len_years[isleap(j)];
                    966:                        ++j;
                    967:                } else {
                    968:                        --j;
                    969:                        i = -len_years[isleap(j)];
                    970:                }
                    971:                dayoff = oadd(dayoff, eitol(i));
                    972:        }
                    973:        if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
                    974:                error("invalid month name");
                    975:                return;
                    976:        }
                    977:        month = lp->l_value;
                    978:        j = TM_JANUARY;
                    979:        while (j != month) {
                    980:                i = len_months[isleap(year)][j];
                    981:                dayoff = oadd(dayoff, eitol(i));
                    982:                ++j;
                    983:        }
                    984:        cp = fields[LP_DAY];
                    985:        if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
                    986:                day <= 0 || day > len_months[isleap(year)][month]) {
                    987:                        error("invalid day of month");
                    988:                        return;
                    989:        }
                    990:        dayoff = oadd(dayoff, eitol(day - 1));
                    991:        if (dayoff < 0 && !tt_signed) {
                    992:                error("time before zero");
                    993:                return;
                    994:        }
                    995:        t = (time_t) dayoff * SECSPERDAY;
                    996:        /*
                    997:        ** Cheap overflow check.
                    998:        */
                    999:        if (t / SECSPERDAY != dayoff) {
                   1000:                error("time overflow");
                   1001:                return;
                   1002:        }
                   1003:        tod = gethms(fields[LP_TIME], "invalid time of day", FALSE);
                   1004:        cp = fields[LP_CORR];
                   1005:        if (strcmp(cp, "+") != 0 && strcmp(cp, "") != 0) {
                   1006:                /* infile() turned "-" into "" */
                   1007:                error("illegal CORRECTION field on Leap line");
                   1008:                return;
                   1009:        }
                   1010:        if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
                   1011:                error("illegal Rolling/Stationary field on Leap line");
                   1012:                return;
                   1013:        }
                   1014:        addleap(tadd(t, tod), *cp == '+', lp->l_value);
                   1015: }
                   1016: 
                   1017: static void
                   1018: inlink(fields, nfields)
                   1019: register char ** const fields;
                   1020: const int              nfields;
                   1021: {
                   1022:        struct link     l;
                   1023: 
                   1024:        if (nfields != LINK_FIELDS) {
                   1025:                error("wrong number of fields on Link line");
                   1026:                return;
                   1027:        }
                   1028:        if (*fields[LF_FROM] == '\0') {
                   1029:                error("blank FROM field on Link line");
                   1030:                return;
                   1031:        }
                   1032:        if (*fields[LF_TO] == '\0') {
                   1033:                error("blank TO field on Link line");
                   1034:                return;
                   1035:        }
                   1036:        l.l_filename = filename;
                   1037:        l.l_linenum = linenum;
                   1038:        l.l_from = ecpyalloc(fields[LF_FROM]);
                   1039:        l.l_to = ecpyalloc(fields[LF_TO]);
                   1040:        links = (struct link *) erealloc((char *) links,
                   1041:                (int) ((nlinks + 1) * sizeof *links));
                   1042:        links[nlinks++] = l;
                   1043: }
                   1044: 
                   1045: static void
                   1046: rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
                   1047: register struct rule * const   rp;
                   1048: char * const                   loyearp;
                   1049: char * const                   hiyearp;
                   1050: char * const                   typep;
                   1051: char * const                   monthp;
                   1052: char * const                   dayp;
                   1053: char * const                   timep;
                   1054: {
                   1055:        register struct lookup const *  lp;
                   1056:        register char *                 cp;
                   1057: 
                   1058:        if ((lp = byword(monthp, mon_names)) == NULL) {
                   1059:                error("invalid month name");
                   1060:                return;
                   1061:        }
                   1062:        rp->r_month = lp->l_value;
                   1063:        rp->r_todisstd = FALSE;
                   1064:        cp = timep;
                   1065:        if (*cp != '\0') {
                   1066:                cp += strlen(cp) - 1;
                   1067:                switch (lowerit(*cp)) {
                   1068:                        case 's':
                   1069:                                rp->r_todisstd = TRUE;
                   1070:                                *cp = '\0';
                   1071:                                break;
                   1072:                        case 'w':
                   1073:                                rp->r_todisstd = FALSE;
                   1074:                                *cp = '\0';
                   1075:                                break;
                   1076:                }
                   1077:        }
                   1078:        rp->r_tod = gethms(timep, "invalid time of day", FALSE);
                   1079:        /*
                   1080:        ** Year work.
                   1081:        */
                   1082:        cp = loyearp;
                   1083:        if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) {
                   1084:                case YR_MINIMUM:
                   1085:                        rp->r_loyear = min_year;
                   1086:                        break;
                   1087:                case YR_MAXIMUM:
                   1088:                        rp->r_loyear = max_year;
                   1089:                        break;
                   1090:                default:        /* "cannot happen" */
                   1091:                        (void) fprintf(stderr,
                   1092:                                "%s: panic: Invalid l_value %d\n",
                   1093:                                progname, lp->l_value);
                   1094:                        (void) exit(EXIT_FAILURE);
                   1095:        } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1 ||
                   1096:                rp->r_loyear < min_year || rp->r_loyear > max_year) {
                   1097:                        if (noise)
                   1098:                                error("invalid starting year");
                   1099:                        if (rp->r_loyear > max_year)
                   1100:                                return;
                   1101:        }
                   1102:        cp = hiyearp;
                   1103:        if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
                   1104:                case YR_MINIMUM:
                   1105:                        rp->r_hiyear = min_year;
                   1106:                        break;
                   1107:                case YR_MAXIMUM:
                   1108:                        rp->r_hiyear = max_year;
                   1109:                        break;
                   1110:                case YR_ONLY:
                   1111:                        rp->r_hiyear = rp->r_loyear;
                   1112:                        break;
                   1113:                default:        /* "cannot happen" */
                   1114:                        (void) fprintf(stderr,
                   1115:                                "%s: panic: Invalid l_value %d\n",
                   1116:                                progname, lp->l_value);
                   1117:                        (void) exit(EXIT_FAILURE);
                   1118:        } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1 ||
                   1119:                rp->r_hiyear < min_year || rp->r_hiyear > max_year) {
                   1120:                        if (noise)
                   1121:                                error("invalid ending year");
                   1122:                        if (rp->r_hiyear < min_year)
                   1123:                                return;
                   1124:        }
                   1125:        if (rp->r_hiyear < min_year)
                   1126:                return;
                   1127:        if (rp->r_loyear < min_year)
                   1128:                rp->r_loyear = min_year;
                   1129:        if (rp->r_hiyear > max_year)
                   1130:                rp->r_hiyear = max_year;
                   1131:        if (rp->r_loyear > rp->r_hiyear) {
                   1132:                error("starting year greater than ending year");
                   1133:                return;
                   1134:        }
                   1135:        if (*typep == '\0')
                   1136:                rp->r_yrtype = NULL;
                   1137:        else {
                   1138:                if (rp->r_loyear == rp->r_hiyear) {
                   1139:                        error("typed single year");
                   1140:                        return;
                   1141:                }
                   1142:                rp->r_yrtype = ecpyalloc(typep);
                   1143:        }
                   1144:        /*
                   1145:        ** Day work.
                   1146:        ** Accept things such as:
                   1147:        **      1
                   1148:        **      last-Sunday
                   1149:        **      Sun<=20
                   1150:        **      Sun>=7
                   1151:        */
                   1152:        if ((lp = byword(dayp, lasts)) != NULL) {
                   1153:                rp->r_dycode = DC_DOWLEQ;
                   1154:                rp->r_wday = lp->l_value;
                   1155:                rp->r_dayofmonth = len_months[1][rp->r_month];
                   1156:        } else {
                   1157:                if ((cp = strchr(dayp, '<')) != 0)
                   1158:                        rp->r_dycode = DC_DOWLEQ;
                   1159:                else if ((cp = strchr(dayp, '>')) != 0)
                   1160:                        rp->r_dycode = DC_DOWGEQ;
                   1161:                else {
                   1162:                        cp = dayp;
                   1163:                        rp->r_dycode = DC_DOM;
                   1164:                }
                   1165:                if (rp->r_dycode != DC_DOM) {
                   1166:                        *cp++ = 0;
                   1167:                        if (*cp++ != '=') {
                   1168:                                error("invalid day of month");
                   1169:                                return;
                   1170:                        }
                   1171:                        if ((lp = byword(dayp, wday_names)) == NULL) {
                   1172:                                error("invalid weekday name");
                   1173:                                return;
                   1174:                        }
                   1175:                        rp->r_wday = lp->l_value;
                   1176:                }
                   1177:                if (sscanf(cp, scheck(cp, "%d"), &rp->r_dayofmonth) != 1 ||
                   1178:                        rp->r_dayofmonth <= 0 ||
                   1179:                        (rp->r_dayofmonth > len_months[1][rp->r_month])) {
                   1180:                                error("invalid day of month");
                   1181:                                return;
                   1182:                }
                   1183:        }
                   1184: }
                   1185: 
                   1186: static void
                   1187: convert(val, buf)
                   1188: const long     val;
                   1189: char * const   buf;
                   1190: {
                   1191:        register int    i;
                   1192:        register long   shift;
                   1193: 
                   1194:        for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
                   1195:                buf[i] = val >> shift;
                   1196: }
                   1197: 
                   1198: static void
                   1199: puttzcode(val, fp)
                   1200: const long     val;
                   1201: FILE * const   fp;
                   1202: {
                   1203:        char    buf[4];
                   1204: 
                   1205:        convert(val, buf);
                   1206:        (void) fwrite((genericptr_t) buf,
                   1207:                (fwrite_size_t) sizeof buf,
                   1208:                (fwrite_size_t) 1, fp);
                   1209: }
                   1210: 
                   1211: static void
                   1212: writezone(name)
                   1213: const char * const     name;
                   1214: {
                   1215:        register FILE *         fp;
                   1216:        register int            i, j;
                   1217:        char                    fullname[BUFSIZ];
                   1218:        static struct tzhead    tzh;
                   1219: 
                   1220:        if (strlen(directory) + 1 + strlen(name) >= sizeof fullname) {
                   1221:                (void) fprintf(stderr,
                   1222:                        "%s: File name %s/%s too long\n", progname,
                   1223:                        directory, name);
                   1224:                (void) exit(EXIT_FAILURE);
                   1225:        }
                   1226:        (void) sprintf(fullname, "%s/%s", directory, name);
                   1227:        if ((fp = fopen(fullname, "wb")) == NULL) {
                   1228:                if (mkdirs(fullname) != 0)
                   1229:                        (void) exit(EXIT_FAILURE);
                   1230:                if ((fp = fopen(fullname, "wb")) == NULL) {
                   1231:                        (void) fprintf(stderr, "%s: Can't create ", progname);
                   1232:                        (void) perror(fullname);
                   1233:                        (void) exit(EXIT_FAILURE);
                   1234:                }
                   1235:        }
                   1236:        convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
                   1237:        convert(eitol(leapcnt), tzh.tzh_leapcnt);
                   1238:        convert(eitol(timecnt), tzh.tzh_timecnt);
                   1239:        convert(eitol(typecnt), tzh.tzh_typecnt);
                   1240:        convert(eitol(charcnt), tzh.tzh_charcnt);
                   1241:        (void) fwrite((genericptr_t) &tzh,
                   1242:                (fwrite_size_t) sizeof tzh,
                   1243:                (fwrite_size_t) 1, fp);
                   1244:        for (i = 0; i < timecnt; ++i) {
                   1245:                j = leapcnt;
                   1246:                while (--j >= 0)
                   1247:                        if (ats[i] >= trans[j]) {
                   1248:                                ats[i] = tadd(ats[i], corr[j]);
                   1249:                                break;
                   1250:                        }
                   1251:                puttzcode((long) ats[i], fp);
                   1252:        }
                   1253:        if (timecnt > 0)
                   1254:                (void) fwrite((genericptr_t) types,
                   1255:                        (fwrite_size_t) sizeof types[0],
                   1256:                        (fwrite_size_t) timecnt, fp);
                   1257:        for (i = 0; i < typecnt; ++i) {
                   1258:                puttzcode((long) gmtoffs[i], fp);
                   1259:                (void) putc(isdsts[i], fp);
                   1260:                (void) putc(abbrinds[i], fp);
                   1261:        }
                   1262:        if (charcnt != 0)
                   1263:                (void) fwrite((genericptr_t) chars,
                   1264:                        (fwrite_size_t) sizeof chars[0],
                   1265:                        (fwrite_size_t) charcnt, fp);
                   1266:        for (i = 0; i < leapcnt; ++i) {
                   1267:                if (roll[i]) {
                   1268:                        if (timecnt == 0 || trans[i] < ats[0]) {
                   1269:                                j = 0;
                   1270:                                while (isdsts[j])
                   1271:                                        if (++j >= typecnt) {
                   1272:                                                j = 0;
                   1273:                                                break;
                   1274:                                        }
                   1275:                        } else {
                   1276:                                j = 1;
                   1277:                                while (j < timecnt && trans[i] >= ats[j])
                   1278:                                        ++j;
                   1279:                                j = types[j - 1];
                   1280:                        }
                   1281:                        puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
                   1282:                } else  puttzcode((long) trans[i], fp);
                   1283:                puttzcode((long) corr[i], fp);
                   1284:        }
                   1285:        for (i = 0; i < typecnt; ++i)
                   1286:                (void) putc(ttisstds[i], fp);
                   1287:        if (ferror(fp) || fclose(fp)) {
                   1288:                (void) fprintf(stderr, "%s: Write error on ", progname);
                   1289:                (void) perror(fullname);
                   1290:                (void) exit(EXIT_FAILURE);
                   1291:        }
                   1292: }
                   1293: 
                   1294: static void
                   1295: outzone(zpfirst, zonecount)
                   1296: const struct zone * const      zpfirst;
                   1297: const int                      zonecount;
                   1298: {
                   1299:        register const struct zone *    zp;
                   1300:        register struct rule *          rp;
                   1301:        register int                    i, j;
                   1302:        register int                    usestart, useuntil;
                   1303:        register time_t                 starttime, untiltime;
                   1304:        register long                   gmtoff;
                   1305:        register long                   stdoff;
                   1306:        register int                    year;
                   1307:        register long                   startoff;
                   1308:        register int                    startisdst;
                   1309:        register int                    startttisstd;
                   1310:        register int                    type;
                   1311:        char                            startbuf[BUFSIZ];
                   1312: 
                   1313:        /*
                   1314:        ** Now. . .finally. . .generate some useful data!
                   1315:        */
                   1316:        timecnt = 0;
                   1317:        typecnt = 0;
                   1318:        charcnt = 0;
                   1319:        /*
                   1320:        ** Two guesses. . .the second may well be corrected later.
                   1321:        */
                   1322:        gmtoff = zpfirst->z_gmtoff;
                   1323:        stdoff = 0;
                   1324: #ifdef lint
                   1325:        starttime = 0;
                   1326:        startttisstd = FALSE;
                   1327: #endif /* defined lint */
                   1328:        for (i = 0; i < zonecount; ++i) {
                   1329:                usestart = i > 0;
                   1330:                useuntil = i < (zonecount - 1);
                   1331:                zp = &zpfirst[i];
                   1332:                eat(zp->z_filename, zp->z_linenum);
                   1333:                startisdst = -1;
                   1334:                if (zp->z_nrules == 0) {
                   1335:                        type = addtype(oadd(zp->z_gmtoff, zp->z_stdoff),
                   1336:                                zp->z_format, zp->z_stdoff != 0,
                   1337:                                startttisstd);
                   1338:                        if (usestart)
                   1339:                                addtt(starttime, type);
                   1340:                        gmtoff = zp->z_gmtoff;
                   1341:                        stdoff = zp->z_stdoff;
                   1342:                } else for (year = min_year; year <= max_year; ++year) {
                   1343:                        if (useuntil && year > zp->z_untilrule.r_hiyear)
                   1344:                                break;
                   1345:                        /*
                   1346:                        ** Mark which rules to do in the current year.
                   1347:                        ** For those to do, calculate rpytime(rp, year);
                   1348:                        */
                   1349:                        for (j = 0; j < zp->z_nrules; ++j) {
                   1350:                                rp = &zp->z_rules[j];
                   1351:                                eats(zp->z_filename, zp->z_linenum,
                   1352:                                        rp->r_filename, rp->r_linenum);
                   1353:                                rp->r_todo = year >= rp->r_loyear &&
                   1354:                                                year <= rp->r_hiyear &&
                   1355:                                                yearistype(year, rp->r_yrtype);
                   1356:                                if (rp->r_todo)
                   1357:                                        rp->r_temp = rpytime(rp, year);
                   1358:                        }
                   1359:                        for ( ; ; ) {
                   1360:                                register int    k;
                   1361:                                register time_t jtime, ktime;
                   1362:                                register long   offset;
                   1363:                                char            buf[BUFSIZ];
                   1364: 
                   1365:                                if (useuntil) {
                   1366:                                        /*
                   1367:                                        ** Turn untiltime into GMT
                   1368:                                        ** assuming the current gmtoff and
                   1369:                                        ** stdoff values.
                   1370:                                        */
                   1371:                                        offset = gmtoff;
                   1372:                                        if (!zp->z_untilrule.r_todisstd)
                   1373:                                                offset = oadd(offset, stdoff);
                   1374:                                        untiltime = tadd(zp->z_untiltime,
                   1375:                                                -offset);
                   1376:                                }
                   1377:                                /*
                   1378:                                ** Find the rule (of those to do, if any)
                   1379:                                ** that takes effect earliest in the year.
                   1380:                                */
                   1381:                                k = -1;
                   1382: #ifdef lint
                   1383:                                ktime = 0;
                   1384: #endif /* defined lint */
                   1385:                                for (j = 0; j < zp->z_nrules; ++j) {
                   1386:                                        rp = &zp->z_rules[j];
                   1387:                                        if (!rp->r_todo)
                   1388:                                                continue;
                   1389:                                        eats(zp->z_filename, zp->z_linenum,
                   1390:                                                rp->r_filename, rp->r_linenum);
                   1391:                                        offset = gmtoff;
                   1392:                                        if (!rp->r_todisstd)
                   1393:                                                offset = oadd(offset, stdoff);
                   1394:                                        jtime = rp->r_temp;
                   1395:                                        if (jtime == min_time ||
                   1396:                                                jtime == max_time)
                   1397:                                                        continue;
                   1398:                                        jtime = tadd(jtime, -offset);
                   1399:                                        if (k < 0 || jtime < ktime) {
                   1400:                                                k = j;
                   1401:                                                ktime = jtime;
                   1402:                                        }
                   1403:                                }
                   1404:                                if (k < 0)
                   1405:                                        break;  /* go on to next year */
                   1406:                                rp = &zp->z_rules[k];
                   1407:                                rp->r_todo = FALSE;
                   1408:                                if (useuntil && ktime >= untiltime)
                   1409:                                        break;
                   1410:                                if (usestart) {
                   1411:                                        if (ktime < starttime) {
                   1412:                                                stdoff = rp->r_stdoff;
                   1413:                                                startoff = oadd(zp->z_gmtoff,
                   1414:                                                        rp->r_stdoff);
                   1415:                                                (void) sprintf(startbuf,
                   1416:                                                        zp->z_format,
                   1417:                                                        rp->r_abbrvar);
                   1418:                                                startisdst =
                   1419:                                                        rp->r_stdoff != 0;
                   1420:                                                continue;
                   1421:                                        }
                   1422:                                        if (ktime != starttime &&
                   1423:                                                startisdst >= 0)
                   1424: addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd));
                   1425:                                        usestart = FALSE;
                   1426:                                }
                   1427:                                eats(zp->z_filename, zp->z_linenum,
                   1428:                                        rp->r_filename, rp->r_linenum);
                   1429:                                (void) sprintf(buf, zp->z_format,
                   1430:                                        rp->r_abbrvar);
                   1431:                                offset = oadd(zp->z_gmtoff, rp->r_stdoff);
                   1432:                                type = addtype(offset, buf, rp->r_stdoff != 0,
                   1433:                                        rp->r_todisstd);
                   1434:                                if (timecnt != 0 || rp->r_stdoff != 0)
                   1435:                                        addtt(ktime, type);
                   1436:                                gmtoff = zp->z_gmtoff;
                   1437:                                stdoff = rp->r_stdoff;
                   1438:                        }
                   1439:                }
                   1440:                /*
                   1441:                ** Now we may get to set starttime for the next zone line.
                   1442:                */
                   1443:                if (useuntil) {
                   1444:                        starttime = tadd(zp->z_untiltime,
                   1445:                                -gmtoffs[types[timecnt - 1]]);
                   1446:                        startttisstd = zp->z_untilrule.r_todisstd;
                   1447:                }
                   1448:        }
                   1449:        writezone(zpfirst->z_name);
                   1450: }
                   1451: 
                   1452: static void
                   1453: addtt(starttime, type)
                   1454: const time_t   starttime;
                   1455: const int      type;
                   1456: {
                   1457:        if (timecnt != 0 && type == types[timecnt - 1])
                   1458:                return; /* easy enough! */
                   1459:        if (timecnt >= TZ_MAX_TIMES) {
                   1460:                error("too many transitions?!");
                   1461:                (void) exit(EXIT_FAILURE);
                   1462:        }
                   1463:        ats[timecnt] = starttime;
                   1464:        types[timecnt] = type;
                   1465:        ++timecnt;
                   1466: }
                   1467: 
                   1468: static int
                   1469: addtype(gmtoff, abbr, isdst, ttisstd)
                   1470: const long             gmtoff;
                   1471: const char * const     abbr;
                   1472: const int              isdst;
                   1473: const int              ttisstd;
                   1474: {
                   1475:        register int    i, j;
                   1476: 
                   1477:        /*
                   1478:        ** See if there's already an entry for this zone type.
                   1479:        ** If so, just return its index.
                   1480:        */
                   1481:        for (i = 0; i < typecnt; ++i) {
                   1482:                if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
                   1483:                        strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
                   1484:                        ttisstd == ttisstds[i])
                   1485:                                return i;
                   1486:        }
                   1487:        /*
                   1488:        ** There isn't one; add a new one, unless there are already too
                   1489:        ** many.
                   1490:        */
                   1491:        if (typecnt >= TZ_MAX_TYPES) {
                   1492:                error("too many local time types");
                   1493:                (void) exit(EXIT_FAILURE);
                   1494:        }
                   1495:        gmtoffs[i] = gmtoff;
                   1496:        isdsts[i] = isdst;
                   1497:        ttisstds[i] = ttisstd;
                   1498: 
                   1499:        for (j = 0; j < charcnt; ++j)
                   1500:                if (strcmp(&chars[j], abbr) == 0)
                   1501:                        break;
                   1502:        if (j == charcnt)
                   1503:                newabbr(abbr);
                   1504:        abbrinds[i] = j;
                   1505:        ++typecnt;
                   1506:        return i;
                   1507: }
                   1508: 
                   1509: static void
                   1510: addleap(t, positive, rolling)
                   1511: const time_t   t;
                   1512: const int      positive;
                   1513: const int      rolling;
                   1514: {
                   1515:        register int    i, j;
                   1516: 
                   1517:        if (leapcnt >= TZ_MAX_LEAPS) {
                   1518:                error("too many leap seconds");
                   1519:                (void) exit(EXIT_FAILURE);
                   1520:        }
                   1521:        for (i = 0; i < leapcnt; ++i)
                   1522:                if (t <= trans[i]) {
                   1523:                        if (t == trans[i]) {
                   1524:                                error("repeated leap second moment");
                   1525:                                (void) exit(EXIT_FAILURE);
                   1526:                        }
                   1527:                        break;
                   1528:                }
                   1529:        for (j = leapcnt; j > i; --j) {
                   1530:                trans[j] = trans[j-1];
                   1531:                corr[j] = corr[j-1];
                   1532:                roll[j] = roll[j-1];
                   1533:        }
                   1534:        trans[i] = t;
                   1535:        corr[i] = (positive ? 1L : -1L);
                   1536:        roll[i] = rolling;
                   1537:        ++leapcnt;
                   1538: }
                   1539: 
                   1540: static void
                   1541: adjleap()
                   1542: {
                   1543:        register int    i;
                   1544:        register long   last = 0;
                   1545: 
                   1546:        /*
                   1547:        ** propagate leap seconds forward
                   1548:        */
                   1549:        for (i = 0; i < leapcnt; ++i) {
                   1550:                trans[i] = tadd(trans[i], last);
                   1551:                last = corr[i] += last;
                   1552:        }
                   1553: }
                   1554: 
                   1555: static int
                   1556: yearistype(year, type)
                   1557: const int              year;
                   1558: const char * const     type;
                   1559: {
                   1560:        char    buf[BUFSIZ];
                   1561:        int     result;
                   1562: 
                   1563:        if (type == NULL || *type == '\0')
                   1564:                return TRUE;
                   1565:        if (strcmp(type, "uspres") == 0)
                   1566:                return (year % 4) == 0;
                   1567:        if (strcmp(type, "nonpres") == 0)
                   1568:                return (year % 4) != 0;
                   1569:        (void) sprintf(buf, "yearistype %d %s", year, type);
                   1570:        result = system(buf);
                   1571:        if (result == 0)
                   1572:                return TRUE;
                   1573:        if (result == (1 << 8))
                   1574:                return FALSE;
                   1575:        error("Wild result from command execution");
                   1576:        (void) fprintf(stderr, "%s: command was '%s', result was %d\n",
                   1577:                progname, buf, result);
                   1578:        for ( ; ; )
                   1579:                (void) exit(EXIT_FAILURE);
                   1580: }
                   1581: 
                   1582: static int
                   1583: lowerit(a)
                   1584: const int      a;
                   1585: {
                   1586:        return (isascii(a) && isupper(a)) ? tolower(a) : a;
                   1587: }
                   1588: 
                   1589: static int
                   1590: ciequal(ap, bp)                /* case-insensitive equality */
                   1591: register const char *  ap;
                   1592: register const char *  bp;
                   1593: {
                   1594:        while (lowerit(*ap) == lowerit(*bp++))
                   1595:                if (*ap++ == '\0')
                   1596:                        return TRUE;
                   1597:        return FALSE;
                   1598: }
                   1599: 
                   1600: static int
                   1601: itsabbr(abbr, word)
                   1602: register const char *  abbr;
                   1603: register const char *  word;
                   1604: {
                   1605:        if (lowerit(*abbr) != lowerit(*word))
                   1606:                return FALSE;
                   1607:        ++word;
                   1608:        while (*++abbr != '\0')
                   1609:                do if (*word == '\0')
                   1610:                        return FALSE;
                   1611:                                while (lowerit(*word++) != lowerit(*abbr));
                   1612:        return TRUE;
                   1613: }
                   1614: 
                   1615: static const struct lookup *
                   1616: byword(word, table)
                   1617: register const char * const            word;
                   1618: register const struct lookup * const   table;
                   1619: {
                   1620:        register const struct lookup *  foundlp;
                   1621:        register const struct lookup *  lp;
                   1622: 
                   1623:        if (word == NULL || table == NULL)
                   1624:                return NULL;
                   1625:        /*
                   1626:        ** Look for exact match.
                   1627:        */
                   1628:        for (lp = table; lp->l_word != NULL; ++lp)
                   1629:                if (ciequal(word, lp->l_word))
                   1630:                        return lp;
                   1631:        /*
                   1632:        ** Look for inexact match.
                   1633:        */
                   1634:        foundlp = NULL;
                   1635:        for (lp = table; lp->l_word != NULL; ++lp)
                   1636:                if (itsabbr(word, lp->l_word))
                   1637:                        if (foundlp == NULL)
                   1638:                                foundlp = lp;
                   1639:                        else    return NULL;    /* multiple inexact matches */
                   1640:        return foundlp;
                   1641: }
                   1642: 
                   1643: static char **
                   1644: getfields(cp)
                   1645: register char *        cp;
                   1646: {
                   1647:        register char *         dp;
                   1648:        register char **        array;
                   1649:        register int            nsubs;
                   1650: 
                   1651:        if (cp == NULL)
                   1652:                return NULL;
                   1653:        array = (char **) emalloc((int) ((strlen(cp) + 1) * sizeof *array));
                   1654:        nsubs = 0;
                   1655:        for ( ; ; ) {
                   1656:                while (isascii(*cp) && isspace(*cp))
                   1657:                        ++cp;
                   1658:                if (*cp == '\0' || *cp == '#')
                   1659:                        break;
                   1660:                array[nsubs++] = dp = cp;
                   1661:                do {
                   1662:                        if ((*dp = *cp++) != '"')
                   1663:                                ++dp;
                   1664:                        else while ((*dp = *cp++) != '"')
                   1665:                                if (*dp != '\0')
                   1666:                                        ++dp;
                   1667:                                else    error("Odd number of quotation marks");
                   1668:                } while (*cp != '\0' && *cp != '#' &&
                   1669:                        (!isascii(*cp) || !isspace(*cp)));
                   1670:                if (isascii(*cp) && isspace(*cp))
                   1671:                        ++cp;
                   1672:                *dp = '\0';
                   1673:        }
                   1674:        array[nsubs] = NULL;
                   1675:        return array;
                   1676: }
                   1677: 
                   1678: static long
                   1679: oadd(t1, t2)
                   1680: const long     t1;
                   1681: const long     t2;
                   1682: {
                   1683:        register long   t;
                   1684: 
                   1685:        t = t1 + t2;
                   1686:        if (t2 > 0 && t <= t1 || t2 < 0 && t >= t1) {
                   1687:                error("time overflow");
                   1688:                (void) exit(EXIT_FAILURE);
                   1689:        }
                   1690:        return t;
                   1691: }
                   1692: 
                   1693: static time_t
                   1694: tadd(t1, t2)
                   1695: const time_t   t1;
                   1696: const long     t2;
                   1697: {
                   1698:        register time_t t;
                   1699: 
                   1700:        if (t1 == max_time && t2 > 0)
                   1701:                return max_time;
                   1702:        if (t1 == min_time && t2 < 0)
                   1703:                return min_time;
                   1704:        t = t1 + t2;
                   1705:        if (t2 > 0 && t <= t1 || t2 < 0 && t >= t1) {
                   1706:                error("time overflow");
                   1707:                (void) exit(EXIT_FAILURE);
                   1708:        }
                   1709:        return t;
                   1710: }
                   1711: 
                   1712: /*
                   1713: ** Given a rule, and a year, compute the date - in seconds since January 1,
                   1714: ** 1970, 00:00 LOCAL time - in that year that the rule refers to.
                   1715: */
                   1716: 
                   1717: static time_t
                   1718: rpytime(rp, wantedy)
                   1719: register const struct rule * const     rp;
                   1720: register const int                     wantedy;
                   1721: {
                   1722:        register int    y, m, i;
                   1723:        register long   dayoff;                 /* with a nod to Margaret O. */
                   1724:        register time_t t;
                   1725: 
                   1726:        dayoff = 0;
                   1727:        m = TM_JANUARY;
                   1728:        y = EPOCH_YEAR;
                   1729:        while (wantedy != y) {
                   1730:                if (wantedy > y) {
                   1731:                        i = len_years[isleap(y)];
                   1732:                        ++y;
                   1733:                } else {
                   1734:                        --y;
                   1735:                        i = -len_years[isleap(y)];
                   1736:                }
                   1737:                dayoff = oadd(dayoff, eitol(i));
                   1738:        }
                   1739:        while (m != rp->r_month) {
                   1740:                i = len_months[isleap(y)][m];
                   1741:                dayoff = oadd(dayoff, eitol(i));
                   1742:                ++m;
                   1743:        }
                   1744:        i = rp->r_dayofmonth;
                   1745:        if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
                   1746:                if (rp->r_dycode == DC_DOWLEQ)
                   1747:                        --i;
                   1748:                else {
                   1749:                        error("use of 2/29 in non leap-year");
                   1750:                        (void) exit(EXIT_FAILURE);
                   1751:                }
                   1752:        }
                   1753:        --i;
                   1754:        dayoff = oadd(dayoff, eitol(i));
                   1755:        if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
                   1756:                register long   wday;
                   1757: 
                   1758: #define LDAYSPERWEEK   ((long) DAYSPERWEEK)
                   1759:                wday = eitol(EPOCH_WDAY);
                   1760:                /*
                   1761:                ** Don't trust mod of negative numbers.
                   1762:                */
                   1763:                if (dayoff >= 0)
                   1764:                        wday = (wday + dayoff) % LDAYSPERWEEK;
                   1765:                else {
                   1766:                        wday -= ((-dayoff) % LDAYSPERWEEK);
                   1767:                        if (wday < 0)
                   1768:                                wday += LDAYSPERWEEK;
                   1769:                }
                   1770:                while (wday != eitol(rp->r_wday))
                   1771:                        if (rp->r_dycode == DC_DOWGEQ) {
                   1772:                                dayoff = oadd(dayoff, (long) 1);
                   1773:                                if (++wday >= LDAYSPERWEEK)
                   1774:                                        wday = 0;
                   1775:                                ++i;
                   1776:                        } else {
                   1777:                                dayoff = oadd(dayoff, (long) -1);
                   1778:                                if (--wday < 0)
                   1779:                                        wday = LDAYSPERWEEK;
                   1780:                                --i;
                   1781:                        }
                   1782:                if (i < 0 || i >= len_months[isleap(y)][m]) {
                   1783:                        error("no day in month matches rule");
                   1784:                        (void) exit(EXIT_FAILURE);
                   1785:                }
                   1786:        }
                   1787:        if (dayoff < 0 && !tt_signed) {
                   1788:                if (wantedy == rp->r_loyear)
                   1789:                        return min_time;
                   1790:                error("time before zero");
                   1791:                (void) exit(EXIT_FAILURE);
                   1792:        }
                   1793:        t = (time_t) dayoff * SECSPERDAY;
                   1794:        /*
                   1795:        ** Cheap overflow check.
                   1796:        */
                   1797:        if (t / SECSPERDAY != dayoff) {
                   1798:                if (wantedy == rp->r_hiyear)
                   1799:                        return max_time;
                   1800:                if (wantedy == rp->r_loyear)
                   1801:                        return min_time;
                   1802:                error("time overflow");
                   1803:                (void) exit(EXIT_FAILURE);
                   1804:        }
                   1805:        return tadd(t, rp->r_tod);
                   1806: }
                   1807: 
                   1808: static void
                   1809: newabbr(string)
                   1810: const char * const     string;
                   1811: {
                   1812:        register int    i;
                   1813: 
                   1814:        i = strlen(string) + 1;
                   1815:        if (charcnt + i >= TZ_MAX_CHARS) {
                   1816:                error("too many, or too long, time zone abbreviations");
                   1817:                (void) exit(EXIT_FAILURE);
                   1818:        }
                   1819:        (void) strcpy(&chars[charcnt], string);
                   1820:        charcnt += eitol(i);
                   1821: }
                   1822: 
                   1823: static int
                   1824: mkdirs(name)
                   1825: char * const   name;
                   1826: {
                   1827:        register char * cp;
                   1828: 
                   1829:        if ((cp = name) == NULL || *cp == '\0')
                   1830:                return 0;
                   1831:        while ((cp = strchr(cp + 1, '/')) != 0) {
                   1832:                *cp = '\0';
                   1833: #ifndef unix
                   1834:                /*
                   1835:                ** MS-DOS drive specifier?
                   1836:                */
                   1837:                if (strlen(name) == 2 && isascii(name[0]) &&
                   1838:                        isalpha(name[0]) && name[1] == ':') {
                   1839:                                *cp = '/';
                   1840:                                continue;
                   1841:                }
                   1842: #endif /* !defined unix */
                   1843:                if (!itsdir(name)) {
                   1844:                        /*
                   1845:                        ** It doesn't seem to exist, so we try to create it.
                   1846:                        */
                   1847:                        if (emkdir(name, 0755) != 0) {
                   1848:                                (void) fprintf(stderr,
                   1849:                                        "%s: Can't create directory ",
                   1850:                                        progname);
                   1851:                                (void) perror(name);
                   1852:                                return -1;
                   1853:                        }
                   1854:                }
                   1855:                *cp = '/';
                   1856:        }
                   1857:        return 0;
                   1858: }
                   1859: 
                   1860: static long
                   1861: eitol(i)
                   1862: const int      i;
                   1863: {
                   1864:        long    l;
                   1865: 
                   1866:        l = i;
                   1867:        if (i < 0 && l >= 0 || i == 0 && l != 0 || i > 0 && l <= 0) {
                   1868:                (void) fprintf(stderr, "%s: %d did not sign extend correctly\n",
                   1869:                        progname, i);
                   1870:                (void) exit(EXIT_FAILURE);
                   1871:        }
                   1872:        return l;
                   1873: }
                   1874: 
                   1875: /*
                   1876: ** UNIX is a registered trademark of AT&T.
                   1877: */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.