⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 linux下的获取Internet time的程式
💻 C
📖 第 1 页 / 共 5 页
字号:
                        argv0);                return;            }            if (buffer.total < 1 || buffer.total > count || buffer.index < 0 ||                    buffer.index >= count || buffer.cycle < 0 ||                    buffer.cycle >= count || buffer.correction < -maxerr ||                    buffer.correction > maxerr || buffer.waiting < RESET_MIN ||                    buffer.waiting > delay || buffer.previous > buffer.when ||                    buffer.previous < buffer.when-count*delay ||                    buffer.when >= *when) {                if (verbose)                    fprintf(stderr,"%s: corrupted restart information\n",argv0);                return;            }/* Checking the record is even more tedious. */            x = *when;            y = 0.0;            for (i = 0; i < buffer.total; ++i) {                if (buffer.record[i].dispersion < 0.0 ||                        buffer.record[i].dispersion > maxerr ||                        buffer.record[i].weight <= 0.0 ||                        buffer.record[i].weight > 1.001/(minerr*minerr) ||                        buffer.record[i].offset < -count*maxerr ||                        buffer.record[i].offset > count*maxerr ||                        buffer.record[i].error < 0.0 ||                        buffer.record[i].error > maxerr) {                    if (verbose)                        fprintf(stderr,"%s: corrupted restart record\n",argv0);                    return;                }                if (buffer.record[i].when < x) x = buffer.record[i].when;                if (buffer.record[i].when > y) y = buffer.record[i].when;            }/* Check for consistency and, finally, whether this is too old. */            if (y > buffer.when || y-x < (buffer.total-1)*delay ||                    y-x > (buffer.total-1)*count*delay) {                if (verbose)                    fprintf(stderr,"%s: corrupted restart times\n",argv0);                return;            }            if (buffer.when < *when-count*delay) {                if (verbose)                    fprintf(stderr,"%s: restart information too old\n",argv0);                return;            }        }/* If we get here, just copy the data back. */        memcpy(record,buffer.record,sizeof(buffer.record));        *previous = buffer.previous;        *when = buffer.when;        *correction = buffer.correction;        *total = buffer.total;        *index = buffer.index;        *cycle = buffer.cycle;        waiting = buffer.waiting;        memset(&buffer,0,sizeof(buffer));/* Print out the data if requested. */        if (verbose > 1) {            fprintf(stderr,"%s: prev=%.3f when=%.3f corr=%.3f\n",                argv0,*previous,*when,*correction);            for (i = 0; i < *total; ++i) {                if ((j = i+*index-*total) < 0) j += *total;                fprintf(stderr,"%s: when=%.3f disp=%.3f off=%.3f",                    argv0,record[j].when,record[j].dispersion,record[j].offset);                if (operation == op_client)                    fprintf(stderr," err=%.3f\n",record[j].error);                else                    fprintf(stderr,"\n");            }        }/* All errors on output are fatal. */    } else if (operation == save_write) {        memcpy(buffer.record,record,sizeof(buffer.record));        buffer.previous = *previous;        buffer.when = *when;        buffer.correction = *correction;        buffer.operation = operation;        buffer.delay = delay;        buffer.count = count;        buffer.total = *total;        buffer.index = *index;        buffer.cycle = *cycle;        buffer.waiting = waiting;        if (fseek(savefile,0l,SEEK_SET) != 0 ||                fwrite(&buffer,sizeof(buffer),1,savefile) != 1 ||                fflush(savefile) != 0 || ferror(savefile))            fatal(1,"unable to write record to daemon save file",NULL);        if (verbose > 2) {            fprintf(stderr,"Writing prev=%.6f when=%.6f corr=%.6f\n",                *previous,*when,*correction);            fprintf(stderr,"op=%d dly=%d cnt=%d tot=%d ind=%d cyc=%d wait=%d\n",                operation,delay,count,*total,*index,*cycle,waiting);            if (*total < COUNT_MAX)                for (i = 0; i < *total; ++i)                    fprintf(stderr,                        "disp=%.6f wgt=%.3f when=%.6f off=%.6f err=%.6f\n",                        record[i].dispersion,record[i].weight,                        record[i].when,record[i].offset,record[i].error);        }/* Clearing the save file is similar. */    } else if (operation == save_clear) {        if (fseek(savefile,0l,SEEK_SET) != 0 ||                fwrite(&buffer,sizeof(buffer),1,savefile) != 1 ||                fflush(savefile) != 0 || ferror(savefile))            fatal(1,"unable to clear daemon save file",NULL);    } else        fatal(0,"internal error in handle_saving",NULL);}void query_savefile (void) {/* This queries a daemon save file. */    double previous, when, correction = 0.0, offset = 0.0, error = -1.0,        drift = 0.0, drifterr = -1.0;    data_record record[COUNT_MAX];    int total = 0, index = 0, cycle = 0;    char text[100];/* This is a few lines stripped out of run_daemon() and slightly hacked. */    previous = when = current_time(JAN_1970);    if (verbose > 2) {        format_time(text,50,0.0,-1.0,0.0,-1.0);        fprintf(stderr,"Started=%.6f %s\n",when,text);    }    handle_saving(save_read_only,&total,&index,&cycle,record,&previous,&when,        &correction);    estimate_stats(&total,&index,record,correction,&dispersion,        &when,&offset,&error,&drift,&drifterr,&waiting,0);    format_time(text,100,offset,error,drift,drifterr);    printf("%s\n",text);    if (fclose(savefile)) fatal(1,"unable to close daemon save file",NULL);    if (verbose > 2) fprintf(stderr,"Stopped normally\n");    exit(EXIT_SUCCESS);}void run_daemon (char *hostnames[], int nhosts, int initial) {/* This does not adjust the time between calls to the server, but it doesadjust the time between clock resets.  This function will survive short periodsof server inaccessibility or network glitches, but not long ones, and will thenneed restarting manually.It is far too complex for a single function, but could really only besimplified by making most of its variables global or by a similarly horribletrick.  Oh, for nested scopes as in Algol 68! */    double history[COUNT_MAX], started, previous, when, correction = 0.0,        weeble = 1.0, accepts = 0.0, rejects = 0.0, flushes = 0.0,        replicates = 0.0, skips = 0.0, offset = 0.0, error = -1.0,        drift = 0.0, drifterr = -1.0, maxoff = 0.0, x;    data_record record[COUNT_MAX];    int total = 0, index = 0, item = 0, rej_level = 0, rep_level = 0,        cycle = 0, retry = 1, i, j, k, ret;    unsigned char transmit[NTP_PACKET_MIN];    ntp_data data;    char text[100];/* After initialising, restore from a previous run if possible.  Note thatonly a few of the variables are actually needed to control the operation andthe rest are mainly for diagnostics. */    started = previous = when = current_time(JAN_1970);    if (verbose > 2) {        format_time(text,50,0.0,-1.0,0.0,-1.0);        fprintf(stderr,"Started=%.6f %s\n",when,text);    }    if (initial) {        handle_saving(save_read_check,&total,&index,&cycle,record,            &previous,&when,&correction);        cycle = (nhosts > 0 ? cycle%nhosts : 0);        if (total > 0 && started-previous < delay) {            if (verbose > 2) fprintf(stderr,"Last packet too recent\n");            retry = 0;        }        if (verbose > 2)            fprintf(stderr,"prev=%.6f when=%.6f retry=%d\n",                previous,when,retry);        for (i = 0; i < nhosts; ++i) open_socket(i,hostnames[i],delay);        if (action != action_display) {            set_lock(1);            locked = 1;        }    }    dispersion = 0.0;    attempts = 0;    for (i = 0; i < count; ++i) history[i] = 0.0;    while (1) {/* Print out a reasonable amount of diagnostics, rather like a server.  Notethat it may take a little time, but shouldn't affect the estimates much.  Thencheck that we aren't in a failing loop. */        if (verbose > 2) fprintf(stderr,"item=%d rej=%d\n",item,rej_level);        x = current_time(JAN_1970)-started;        if (verbose &&                x/3600.0+accepts+rejects+flushes+replicates+skips >= weeble) {            weeble *= WEEBLE_FACTOR;            x -= 3600.0*(i = (int)(x/3600.0));            x -= 60.0*(j = (int)(x/60.0));            if (i > 0)                fprintf(stderr,"%s: after %d hours %d mins ",argv0,i,j);            else if (j > 0)                fprintf(stderr,"%s: after %d mins %.0f secs ",argv0,j,x);            else                fprintf(stderr,"%s: after %.1f secs ",argv0,x);            fprintf(stderr,"acc. %.0f rej. %.0f flush %.0f",                accepts,rejects,flushes);            if (operation == op_listen)                fprintf(stderr," rep. %.0f skip %.0f",replicates,skips);            fprintf(stderr," max.off. %.3f corr. %.3f\n",maxoff,correction);            format_time(text,100,offset,error,drift,drifterr);            fprintf(stderr,"%s: %s\n",argv0,text);            maxoff = 0.0;        }        if (current_time(JAN_1970)-previous > count*delay) {            if (verbose)                fprintf(stderr,"%s: no packets in too long a period\n",argv0);            return;        }/* Listen for the next broadcast packet.  This allows up to ETHERNET_MAXreplications per packet, for systems with multiple addresses for receivingbroadcasts; the only reason for a limit is to protect against broken NTPservers always returning the same time. */        if (operation == op_listen) {            flush_socket(0, &k);            flushes += k;            if (read_packet(0,&data,&offset,&error)) {                ++rejects;                if (++rej_level > count)                    fatal(0,"too many bad or lost packets",NULL);                if (action != action_display && drifterr >= 0.0) {                    correction += correct_drift(&when,&offset,drift);                    handle_saving(save_write,&total,&index,&cycle,record,                        &previous,&when,&correction);                }                continue;            }            if ((rej_level -= (count < 5 ? count : 5)) < 0) rej_level = 0;            x = data.transmit;            for (i = 0; i < count; ++i)                if (x == history[i]) {                    ++replicates;                    if (++rep_level > ETHERNET_MAX)                        fatal(0,"too many replicated packets",NULL);                    goto continue1;                }            rep_level = 0;            history[item] = x;            if (++item >= count) item = 0;/* Accept a packet only after a long enough period has elapsed. */            when = data.current;            if (! retry && when < previous+delay) {                if (verbose > 2) fprintf(stderr,"Skipping too recent packet\n");                ++skips;                continue;            }            retry = 0;            if (verbose > 2)                fprintf(stderr,"Offset=%.6f @ %.6f disp=%.6f\n",                    offset,when,dispersion);/* Handle the client/server model.  It keeps a record of transmitted times,mainly out of paranoia.  The waiting time is kludged up to attempt to providereasonable resilience against both lost packets and dead servers.  But itwon't handle much of either, and will stop after a while, needing manualrestarting.  Running it under cron is the best approach. */        } else {            if (! retry) {               if (verbose > 2) fprintf(stderr,"Sleeping for %d\n",waiting);               do_nothing(waiting);            }            make_packet(&data,NTP_CLIENT);            outgoing[item] = data.transmit;            if (++item >= 2*count) item = 0;            if (attempts < 2*count) ++attempts;            if (verbose > 2) {                fprintf(stderr,"Outgoing packet on socket %d:\n",cycle);                display_data(&data);            }            pack_ntp(transmit,NTP_PACKET_MIN,&data);            if (verbose > 2) display_packet(transmit,NTP_PACKET_MIN);            flush_socket(cycle, &k);            flushes += k;            write_socket(cycle,transmit,NTP_PACKET_MIN);/* Read the packet and check that it is an appropriate response.  Because thisis rather more numerically sensitive than simple resynchronisation, reject allvery inaccurate packets.  Be careful if you modify this, because the errorhandling is rather nasty to avoid replicating code. */            k = read_packet(cycle,&data,&offset,&error);            if (++cycle >= nhosts) cycle = 0;            if (! k)                when = (data.originate+data.current)/2.0;            else if (action != action_display && drifterr >= 0.0) {                correction += correct_drift(&when,&offset,drift);                handle_saving(save_write,&total,&index,&cycle,record,                    &previous,&when,&correction);            }            if (! k && ! retry && when < previous+delay-2) {                if (verbose)                    fprintf(stderr,"%s: packets out of order on socket %d\n",                        argv0,cycle);                k = 1;            }            if (! k && data.current-data.originate > maxerr) {                if (verbose)                    fprintf(stderr,                        "%s: very slow response rejected on socket %d\n",                        argv0,cycle);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -