1/*
2   Samba Unix/Linux SMB client library
3   net time command
4   Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20#include "includes.h"
21#include "utils/net.h"
22
23
24/*
25  return the time on a server. This does not require any authentication
26*/
27static time_t cli_servertime(const char *host, struct in_addr *ip, int *zone)
28{
29	struct nmb_name calling, called;
30	time_t ret = 0;
31	struct cli_state *cli = NULL;
32
33	cli = cli_initialise(NULL);
34	if (!cli) goto done;
35
36	if (!cli_connect(cli, host, ip)) {
37		fprintf(stderr,"Can't contact server\n");
38		goto done;
39	}
40
41	make_nmb_name(&calling, global_myname(), 0x0);
42	if (host) {
43		make_nmb_name(&called, host, 0x20);
44	} else {
45		make_nmb_name(&called, "*SMBSERVER", 0x20);
46	}
47
48	if (!cli_session_request(cli, &calling, &called)) {
49		fprintf(stderr,"Session request failed\n");
50		goto done;
51	}
52	if (!cli_negprot(cli)) {
53		fprintf(stderr,"Protocol negotiation failed\n");
54		goto done;
55	}
56
57	ret = cli->servertime;
58	if (zone) *zone = cli->serverzone;
59
60done:
61	if (cli) cli_shutdown(cli);
62	return ret;
63}
64
65/* find the servers time on the opt_host host */
66static time_t nettime(int *zone)
67{
68	return cli_servertime(opt_host, opt_have_ip? &opt_dest_ip : NULL, zone);
69}
70
71/* return a time as a string ready to be passed to /bin/date */
72static char *systime(time_t t)
73{
74	static fstring s;
75	struct tm *tm;
76
77	tm = localtime(&t);
78
79	fstr_sprintf(s, "%02d%02d%02d%02d%04d.%02d",
80		 tm->tm_mon+1, tm->tm_mday, tm->tm_hour,
81		 tm->tm_min, tm->tm_year + 1900, tm->tm_sec);
82	return s;
83}
84
85int net_time_usage(int argc, const char **argv)
86{
87	d_printf(
88"net time\n\tdisplays time on a server\n\n"\
89"net time system\n\tdisplays time on a server in a format ready for /bin/date\n\n"\
90"net time set\n\truns /bin/date with the time from the server\n\n"\
91"net time zone\n\tdisplays the timezone in hours from GMT on the remote computer\n\n"\
92"\n");
93	net_common_flags_usage(argc, argv);
94	return -1;
95}
96
97/* try to set the system clock using /bin/date */
98static int net_time_set(int argc, const char **argv)
99{
100	time_t t = nettime(NULL);
101	char *cmd;
102
103	if (t == 0) return -1;
104
105	/* yes, I know this is cheesy. Use "net time system" if you want to
106	   roll your own. I'm putting this in as it works on a large number
107	   of systems and the user has a choice in whether its used or not */
108	asprintf(&cmd, "/bin/date %s", systime(t));
109	system(cmd);
110	free(cmd);
111
112	return 0;
113}
114
115/* display the time on a remote box in a format ready for /bin/date */
116static int net_time_system(int argc, const char **argv)
117{
118	time_t t = nettime(NULL);
119
120	if (t == 0) return -1;
121
122	printf("%s\n", systime(t));
123
124	return 0;
125}
126
127/* display the time on a remote box in a format ready for /bin/date */
128static int net_time_zone(int argc, const char **argv)
129{
130	int zone = 0;
131	int hours, mins;
132	char zsign;
133	time_t t;
134
135	t = nettime(&zone);
136
137	if (t == 0) return -1;
138
139	zsign = (zone > 0) ? '-' : '+';
140	if (zone < 0) zone = -zone;
141
142	zone /= 60;
143	hours = zone / 60;
144	mins = zone % 60;
145
146	printf("%c%02d%02d\n", zsign, hours, mins);
147
148	return 0;
149}
150
151/* display or set the time on a host */
152int net_time(int argc, const char **argv)
153{
154	time_t t;
155	struct functable func[] = {
156		{"SYSTEM", net_time_system},
157		{"SET", net_time_set},
158		{"ZONE", net_time_zone},
159		{NULL, NULL}
160	};
161
162	if (!opt_host && !opt_have_ip &&
163	    !find_master_ip(opt_target_workgroup, &opt_dest_ip)) {
164		d_printf("Could not locate a time server.  Try "\
165				 "specifying a target host.\n");
166		net_time_usage(argc,argv);
167		return -1;
168	}
169
170	if (argc != 0) {
171		return net_run_function(argc, argv, func, net_time_usage);
172	}
173
174	/* default - print the time */
175	t = cli_servertime(opt_host, opt_have_ip? &opt_dest_ip : NULL, NULL);
176	if (t == 0) return -1;
177
178	d_printf("%s", ctime(&t));
179	return 0;
180}
181