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

📄 timed.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1985, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1985, 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)timed.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#ifdef sgi#ident "$Revision: 1.25 $"#endif /* sgi */#define TSPTYPES#include "globals.h"#include <net/if.h>#include <sys/file.h>#include <sys/ioctl.h>#include <setjmp.h>#include "pathnames.h"#include <math.h>#include <sys/types.h>#include <sys/times.h>#ifdef sgi#include <unistd.h>#include <sys/syssgi.h>#include <sys/schedctl.h>#endif /* sgi */int trace = 0;int sock, sock_raw = -1;int status = 0;u_short sequence;			/* sequence number */long delay1;long delay2;int nslavenets;				/* nets were I could be a slave */int nmasternets;			/* nets were I could be a master */int nignorednets;			/* ignored nets */int nnets;				/* nets I am connected to */FILE *fd;				/* trace file FD */jmp_buf jmpenv;struct netinfo *nettab = 0;struct netinfo *slavenet;int Mflag;int justquit = 0;int debug;static struct nets {	char	*name;	long	net;	struct nets *next;} *nets = 0;struct hosttbl hosttbl[NHOSTS+1];	/* known hosts */static struct goodhost {		/* hosts that we trust */	char	name[MAXHOSTNAMELEN+1];	struct goodhost *next;	char	perm;} *goodhosts;static char *goodgroup;			/* net group of trusted hosts */static void checkignorednets __P((void));static void pickslavenet __P((struct netinfo *));static void add_good_host __P((char *, int));#ifdef sgichar *timetrim_fn;char *timetrim_wpat = "long timetrim = %ld;\ndouble tot_adj = %.0f;\ndouble tot_ticks = %.0f;\n/* timed version 2 */\n";char *timetrim_rpat = "long timetrim = %ld;\ndouble tot_adj = %lf;\ndouble tot_ticks = %lf;";long timetrim;double tot_adj, hr_adj;			/* totals in nsec */double tot_ticks, hr_ticks;int bufspace = 60*1024;#endif/* * The timedaemons synchronize the clocks of hosts in a local area network. * One daemon runs as master, all the others as slaves. The master * performs the task of computing clock differences and sends correction * values to the slaves. * Slaves start an election to choose a new master when the latter disappears * because of a machine crash, network partition, or when killed. * A resolution protocol is used to kill all but one of the masters * that happen to exist in segments of a partitioned network when the * network partition is fixed. * * Authors: Riccardo Gusella & Stefano Zatti * * overhauled at Silicon Graphics */intmain(argc, argv)	int argc;	char *argv[];{	int on;	int ret;	int nflag, iflag;	struct timeval ntime;	struct servent *srvp;	char buf[BUFSIZ], *cp, *cplim;	struct ifconf ifc;	struct ifreq ifreq, ifreqf, *ifr;	register struct netinfo *ntp;	struct netinfo *ntip;	struct netinfo *savefromnet;	struct netent *nentp;	struct nets *nt;	struct sockaddr_in server;	u_short port;	char c;	extern char *optarg;	extern int optind, opterr;#ifdef sgi	FILE *timetrim_st;#endif#define	IN_MSG "timed: -i and -n make no sense together\n"#ifdef sgi	struct tms tms;#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp] [-P trimfile]\n"#else#ifdef HAVENIS#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp]\n"#else#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...]\n"#endif /* HAVENIS */#endif /* sgi */#ifdef lint	ntip = NULL;#endif	on = 1;	nflag = OFF;	iflag = OFF;#ifdef sgi	if (0 > syssgi(SGI_GETTIMETRIM, &timetrim)) {		perror("timed: syssgi(GETTIMETRIM)");		timetrim = 0;	}	tot_ticks = hr_ticks = times(&tms);#endif /* sgi */	opterr = 0;	while ((c = getopt(argc, argv, "Mtdn:i:F:G:P:")) != EOF) {		switch (c) {		case 'M':			Mflag = 1;			break;		case 't':			trace = 1;			break;		case 'n':			if (iflag) {				fprintf(stderr, IN_MSG);				exit(1);			} else {				nflag = ON;				addnetname(optarg);			}			break;		case 'i':			if (nflag) {				fprintf(stderr, IN_MSG);				exit(1);			} else {				iflag = ON;				addnetname(optarg);			}			break;		case 'F':			add_good_host(optarg,1);			while (optind < argc && argv[optind][0] != '-')				add_good_host(argv[optind++], 1);			break;		case 'd':			debug = 1;			break;		case 'G':			if (goodgroup != 0) {				fprintf(stderr,"timed: only one net group\n");				exit(1);			}			goodgroup = optarg;			break;#ifdef sgi		case 'P':			timetrim_fn = optarg;			timetrim_st = fopen(timetrim_fn, "r+");			if (0 == timetrim_st) {				if (errno != ENOENT) {					(void)fprintf(stderr,"timed: ");					perror(timetrim_fn);					timetrim_fn = 0;				}			} else {				int i;				long trim;				double adj, ticks;				i = fscanf(timetrim_st, timetrim_rpat,					   &trim, &adj, &ticks);				if (i < 1				    || trim > MAX_TRIM				    || trim < -MAX_TRIM				    || i == 2				    || (i == 3					&& trim != rint(adj*CLK_TCK/ticks))) {					if (trace && i != EOF)						(void)fprintf(stderr,				    "timed: unrecognized contents in %s\n",							      timetrim_fn);				} else {					if (0 > syssgi(SGI_SETTIMETRIM,						       trim)) {					 perror("timed: syssgi(SETTIMETRIM)");					} else {						timetrim = trim;					}					if (i == 3) {						tot_adj = adj;						tot_ticks -= ticks;					}				}				(void)fclose(timetrim_st);			}			break;#endif /* sgi */		default:			fprintf(stderr, USAGE);			exit(1);			break;		}	}	if (optind < argc) {		fprintf(stderr, USAGE);		exit(1);	}	/* If we care about which machine is the master, then we must	 *	be willing to be a master	 */	if (0 != goodgroup || 0 != goodhosts)		Mflag = 1;	if (gethostname(hostname, sizeof(hostname) - 1) < 0) {		perror("gethostname");		exit(1);	}	self.l_bak = &self;	self.l_fwd = &self;	self.h_bak = &self;	self.h_fwd = &self;	self.head = 1;	self.good = 1;	if (goodhosts != 0)		/* trust ourself */		add_good_host(hostname,1);	srvp = getservbyname("timed", "udp");	if (srvp == 0) {		fprintf(stderr, "unknown service 'timed/udp'\n");		exit(1);	}	port = srvp->s_port;	server.sin_port = srvp->s_port;	server.sin_family = AF_INET;	sock = socket(AF_INET, SOCK_DGRAM, 0);	if (sock < 0) {		perror("socket");		exit(1);	}	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on,							sizeof(on)) < 0) {		perror("setsockopt");		exit(1);	}	if (bind(sock, (struct sockaddr*)&server, sizeof(server))) {		if (errno == EADDRINUSE)			fprintf(stderr,"timed: time daemon already running\n");		else			perror("bind");		exit(1);	}#ifdef sgi	/*	 * handle many slaves with our buffer	 */	if (0 > setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufspace,			 sizeof(bufspace))) {		perror("setsockopt");		exit(1);	}#endif /* sgi */	/* choose a unique seed for random number generation */	(void)gettimeofday(&ntime, 0);	srandom(ntime.tv_sec + ntime.tv_usec);	sequence = random();     /* initial seq number */#ifndef sgi	/* rounds kernel variable time to multiple of 5 ms. */	ntime.tv_sec = 0;	ntime.tv_usec = -((ntime.tv_usec/1000) % 5) * 1000;	(void)adjtime(&ntime, (struct timeval *)0);#endif /* sgi */	for (nt = nets; nt; nt = nt->next) {		nentp = getnetbyname(nt->name);		if (nentp == 0) {			nt->net = inet_network(nt->name);			if (nt->net != INADDR_NONE)				nentp = getnetbyaddr(nt->net, AF_INET);		}		if (nentp != 0) {			nt->net = nentp->n_net;		} else if (nt->net == INADDR_NONE) {			fprintf(stderr, "timed: unknown net %s\n", nt->name);			exit(1);		} else if (nt->net == INADDR_ANY) {			fprintf(stderr, "timed: bad net %s\n", nt->name);			exit(1);		} else {			fprintf(stderr,				"timed: warning: %s unknown in /etc/networks\n",				nt->name);		}		if (0 == (nt->net & 0xff000000))		    nt->net <<= 8;		if (0 == (nt->net & 0xff000000))		    nt->net <<= 8;		if (0 == (nt->net & 0xff000000))		    nt->net <<= 8;	}	ifc.ifc_len = sizeof(buf);	ifc.ifc_buf = buf;	if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {		perror("timed: get interface configuration");		exit(1);	}	ntp = NULL;#ifdef sgi#define size(p)	(sizeof(*ifr) - sizeof(ifr->ifr_name))  /* XXX hack. kludge */#else#define size(p)	max((p).sa_len, sizeof(p))#endif	cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */	for (cp = buf; cp < cplim;			cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {		ifr = (struct ifreq *)cp;		if (ifr->ifr_addr.sa_family != AF_INET)			continue;		if (!ntp)			ntp = (struct netinfo*)malloc(sizeof(struct netinfo));		bzero(ntp,sizeof(*ntp));		ntp->my_addr=((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;		ntp->status = NOMASTER;		ifreq = *ifr;		ifreqf = *ifr;		if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreqf) < 0) {			perror("get interface flags");			continue;		}		if ((ifreqf.ifr_flags & IFF_UP) == 0)			continue;		if ((ifreqf.ifr_flags & IFF_BROADCAST) == 0 &&		    (ifreqf.ifr_flags & IFF_POINTOPOINT) == 0) {			continue;		}		if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) {			perror("get netmask");			continue;		}		ntp->mask = ((struct sockaddr_in *)			&ifreq.ifr_addr)->sin_addr.s_addr;		if (ifreqf.ifr_flags & IFF_BROADCAST) {			if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {				perror("get broadaddr");				continue;			}			ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_broadaddr;			/* What if the broadcast address is all ones?			 * So we cannot just mask ntp->dest_addr.  */			ntp->net = ntp->my_addr;			ntp->net.s_addr &= ntp->mask;		} else {			if (ioctl(sock, SIOCGIFDSTADDR,						(char *)&ifreq) < 0) {				perror("get destaddr");				continue;			}			ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_dstaddr;			ntp->net = ntp->dest_addr.sin_addr;		}		ntp->dest_addr.sin_port = port;		for (nt = nets; nt; nt = nt->next) {			if (ntp->net.s_addr == nt->net)				break;		}		if (nflag && !nt || iflag && nt)			continue;		ntp->next = NULL;		if (nettab == NULL) {			nettab = ntp;		} else {			ntip->next = ntp;		}		ntip = ntp;		ntp = NULL;	}	if (ntp)		(void) free((char *)ntp);	if (nettab == NULL) {		fprintf(stderr, "timed: no network usable\n");		exit(1);	}#ifdef sgi	(void)schedctl(RENICE,0,10);	   /* run fast to get good time */	/* ticks to delay before responding to a broadcast */	delay1 = casual(0, CLK_TCK/10);#else	/* microseconds to delay before responding to a broadcast */	delay1 = casual(1, 100*1000);#endif /* sgi */	/* election timer delay in secs. */	delay2 = casual(MINTOUT, MAXTOUT);

⌨️ 快捷键说明

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