GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/rdate/rdate.c Lines: 0 72 0.0 %
Date: 2017-11-07 Branches: 0 51 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: rdate.c,v 1.35 2015/12/23 19:13:52 deraadt Exp $	*/
2
/*	$NetBSD: rdate.c,v 1.4 1996/03/16 12:37:45 pk Exp $	*/
3
4
/*
5
 * Copyright (c) 1994 Christos Zoulas
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. All advertising materials mentioning features or use of this software
17
 *    must display the following acknowledgement:
18
 *	This product includes software developed by Christos Zoulas.
19
 * 4. The name of the author may not be used to endorse or promote products
20
 *    derived from this software without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
 */
33
34
/*
35
 * rdate.c: Set the date from the specified host
36
 *
37
 *	Time is returned as the number of seconds since
38
 *	midnight January 1st 1900.
39
 */
40
41
#include <sys/socket.h>
42
#include <sys/time.h>
43
#include <sys/wait.h>
44
45
#include <stdio.h>
46
#include <stdlib.h>
47
#include <ctype.h>
48
#include <err.h>
49
#include <string.h>
50
#include <unistd.h>
51
#include <time.h>
52
53
/* there are systems without libutil; for portability */
54
#ifndef NO_UTIL
55
#include <util.h>
56
#else
57
#define logwtmp(a,b,c)
58
#endif
59
60
void rfc868time_client(const char *, int, struct timeval *, struct timeval *, int);
61
void ntp_client(const char *, int, struct timeval *, struct timeval *, int);
62
63
extern char    *__progname;
64
__dead void	usage(void);
65
66
struct {
67
	char message[2048];
68
	struct timeval new;
69
	struct timeval adjust;
70
} pdata;
71
72
__dead void
73
usage(void)
74
{
75
	(void) fprintf(stderr, "usage: %s [-46acnopsv] host\n", __progname);
76
	exit(1);
77
}
78
79
int
80
main(int argc, char **argv)
81
{
82
	int             pr = 0, silent = 0, ntp = 1, verbose = 0;
83
	int		slidetime = 0, corrleaps = 0;
84
	char           *hname;
85
	extern int      optind;
86
	int             c, p[2], pid;
87
	int		family = PF_UNSPEC;
88
89
	while ((c = getopt(argc, argv, "46psanocv")) != -1) {
90
		switch (c) {
91
		case '4':
92
			family = PF_INET;
93
			break;
94
95
		case '6':
96
			family = PF_INET6;
97
			break;
98
99
		case 'p':
100
			pr = 1;
101
			break;
102
103
		case 's':
104
			silent = 1;
105
			break;
106
107
		case 'a':
108
			slidetime = 1;
109
			break;
110
111
		case 'n':
112
			ntp = 1;
113
			break;
114
115
		case 'o':
116
			ntp = 0;
117
			break;
118
119
		case 'c':
120
			corrleaps = 1;
121
			break;
122
123
		case 'v':
124
			verbose = 1;
125
			break;
126
127
		default:
128
			usage();
129
		}
130
	}
131
	if (argc - 1 != optind)
132
		usage();
133
	hname = argv[optind];
134
135
	/*
136
	 * Privilege separation increases safety, with a slight reduction
137
	 * in precision because the time values have to return over a pipe.
138
	 */
139
	if (pipe(p) == -1)
140
		err(1, "pipe");
141
	switch ((pid = fork())) {
142
	case -1:
143
		err(1, "fork");
144
		break;
145
	case 0:
146
		if (pledge("stdio inet dns flock rpath cpath wpath", NULL) == -1)
147
			err(1, "pledge");
148
149
		close(p[0]);	/* read side of pipe */
150
		dup2(p[1], STDIN_FILENO);
151
		if (p[1] != STDIN_FILENO)
152
			close(p[1]);
153
		dup2(STDIN_FILENO, STDOUT_FILENO);
154
		dup2(STDOUT_FILENO, STDERR_FILENO);
155
		setvbuf(stdout, NULL, _IOFBF, 0);
156
		setvbuf(stderr, NULL, _IOFBF, 0);
157
158
		if (ntp)
159
			ntp_client(hname, family, &pdata.new,
160
			    &pdata.adjust, corrleaps);
161
		else
162
			rfc868time_client(hname, family, &pdata.new,
163
			    &pdata.adjust, corrleaps);
164
165
		if (write(STDOUT_FILENO, &pdata, sizeof pdata) != sizeof pdata)
166
			exit(1);
167
		exit(0);
168
	}
169
170
	if (pledge("stdio rpath wpath settime flock cpath", NULL) == -1)
171
		err(1, "pledge");
172
173
	close(p[1]);	/* write side of pipe */
174
	if (read(p[0], &pdata, sizeof pdata) < 1)
175
		err(1, "child did not collect time");
176
	if (waitpid(pid, NULL, 0) == -1)
177
		err(1, "waitpid");
178
179
	/*
180
	 * A viable timestamp from the child contains no message.
181
	 */
182
	if (pdata.message[0]) {
183
		pdata.message[sizeof(pdata.message)- 1] = '\0';
184
		write(STDERR_FILENO, pdata.message, strlen(pdata.message));
185
		exit(1);
186
	}
187
188
	if (!pr) {
189
		if (!slidetime) {
190
			logwtmp("|", "date", "");
191
			if (settimeofday(&pdata.new, NULL) == -1)
192
				err(1, "Could not set time of day");
193
			logwtmp("{", "date", "");
194
		} else {
195
			if (adjtime(&pdata.adjust, NULL) == -1)
196
				err(1, "Could not adjust time of day");
197
		}
198
	}
199
200
	if (pledge("stdio rpath flock cpath wpath", NULL) == -1)
201
		err(1, "pledge");
202
203
	if (!silent) {
204
		struct tm      *ltm;
205
		char		buf[80];
206
		time_t		tim = pdata.new.tv_sec;
207
		double		adjsec;
208
209
		ltm = localtime(&tim);
210
		(void) strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %Z %Y\n", ltm);
211
		(void) fputs(buf, stdout);
212
213
		adjsec  = pdata.adjust.tv_sec + pdata.adjust.tv_usec / 1.0e6;
214
215
		if (slidetime || verbose) {
216
			if (ntp)
217
				(void) fprintf(stdout,
218
				   "%s: adjust local clock by %.6f seconds\n",
219
				   __progname, adjsec);
220
			else
221
				(void) fprintf(stdout,
222
				   "%s: adjust local clock by %lld seconds\n",
223
				   __progname, (long long)pdata.adjust.tv_sec);
224
		}
225
	}
226
227
	return 0;
228
}