73f0315b1d55530dc6132ed7434bd3b0eeb7a6d1
[samba.git] / source3 / utils / net_time.c
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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19 #include "includes.h"
20 #include "utils/net.h"
21
22
23 /*
24   return the time on a server. This does not require any authentication
25 */
26 static time_t cli_servertime(const char *host, struct sockaddr_storage *pss, int *zone)
27 {
28         struct nmb_name calling, called;
29         time_t ret = 0;
30         struct cli_state *cli = NULL;
31         NTSTATUS status;
32
33         cli = cli_initialise();
34         if (!cli) {
35                 goto done;
36         }
37
38         status = cli_connect(cli, host, pss);
39         if (!NT_STATUS_IS_OK(status)) {
40                 fprintf(stderr,"Can't contact server %s. Error %s\n", host, nt_errstr(status));
41                 goto done;
42         }
43
44         make_nmb_name(&calling, global_myname(), 0x0);
45         if (host) {
46                 make_nmb_name(&called, host, 0x20);
47         } else {
48                 make_nmb_name(&called, "*SMBSERVER", 0x20);
49         }
50
51         if (!cli_session_request(cli, &calling, &called)) {
52                 fprintf(stderr,"Session request failed\n");
53                 goto done;
54         }
55         if (!cli_negprot(cli)) {
56                 fprintf(stderr,"Protocol negotiation failed\n");
57                 goto done;
58         }
59
60         ret = cli->servertime;
61         if (zone) *zone = cli->serverzone;
62
63 done:
64         if (cli) {
65                 cli_shutdown(cli);
66         }
67         return ret;
68 }
69
70 /* find the servers time on the opt_host host */
71 static time_t nettime(struct net_context *c, int *zone)
72 {
73         return cli_servertime(c->opt_host,
74                               c->opt_have_ip? &c->opt_dest_ip : NULL, zone);
75 }
76
77 /* return a time as a string ready to be passed to /bin/date */
78 static const char *systime(time_t t)
79 {
80         static fstring s;
81         struct tm *tm;
82
83         tm = localtime(&t);
84         if (!tm) {
85                 return "unknown";
86         }
87
88         fstr_sprintf(s, "%02d%02d%02d%02d%04d.%02d",
89                  tm->tm_mon+1, tm->tm_mday, tm->tm_hour,
90                  tm->tm_min, tm->tm_year + 1900, tm->tm_sec);
91         return s;
92 }
93
94 int net_time_usage(struct net_context *c, int argc, const char **argv)
95 {
96         d_printf(
97 "net time\n\tdisplays time on a server\n\n"\
98 "net time system\n\tdisplays time on a server in a format ready for /bin/date\n\n"\
99 "net time set\n\truns /bin/date with the time from the server\n\n"\
100 "net time zone\n\tdisplays the timezone in hours from GMT on the remote computer\n\n"\
101 "\n");
102         net_common_flags_usage(c, argc, argv);
103         return -1;
104 }
105
106 /* try to set the system clock using /bin/date */
107 static int net_time_set(struct net_context *c, int argc, const char **argv)
108 {
109         time_t t = nettime(c, NULL);
110         char *cmd;
111         int result;
112
113         if (t == 0) return -1;
114
115         /* yes, I know this is cheesy. Use "net time system" if you want to
116            roll your own. I'm putting this in as it works on a large number
117            of systems and the user has a choice in whether its used or not */
118         asprintf(&cmd, "/bin/date %s", systime(t));
119         result = system(cmd);
120         if (result)
121                 d_fprintf(stderr, "%s failed.  Error was (%s)\n",
122                         cmd, strerror(errno));
123         free(cmd);
124
125         return result;
126 }
127
128 /* display the time on a remote box in a format ready for /bin/date */
129 static int net_time_system(struct net_context *c, int argc, const char **argv)
130 {
131         time_t t = nettime(c, NULL);
132
133         if (t == 0) return -1;
134
135         printf("%s\n", systime(t));
136
137         return 0;
138 }
139
140 /* display the time on a remote box in a format ready for /bin/date */
141 static int net_time_zone(struct net_context *c, int argc, const char **argv)
142 {
143         int zone = 0;
144         int hours, mins;
145         char zsign;
146         time_t t;
147
148         t = nettime(c, &zone);
149
150         if (t == 0) return -1;
151
152         zsign = (zone > 0) ? '-' : '+';
153         if (zone < 0) zone = -zone;
154
155         zone /= 60;
156         hours = zone / 60;
157         mins = zone % 60;
158
159         printf("%c%02d%02d\n", zsign, hours, mins);
160
161         return 0;
162 }
163
164 /* display or set the time on a host */
165 int net_time(struct net_context *c, int argc, const char **argv)
166 {
167         time_t t;
168         struct functable func[] = {
169                 {"SYSTEM", net_time_system},
170                 {"SET", net_time_set},
171                 {"ZONE", net_time_zone},
172                 {NULL, NULL}
173         };
174
175         if (!c->opt_host && !c->opt_have_ip &&
176             !find_master_ip(c->opt_target_workgroup, &c->opt_dest_ip)) {
177                 d_fprintf(stderr, "Could not locate a time server.  Try "\
178                                  "specifying a target host.\n");
179                 net_time_usage(c, argc,argv);
180                 return -1;
181         }
182
183         if (argc != 0) {
184                 return net_run_function(c, argc, argv, func, net_time_usage);
185         }
186
187         /* default - print the time */
188         t = cli_servertime(c->opt_host, c->opt_have_ip? &c->opt_dest_ip : NULL,
189                            NULL);
190         if (t == 0) return -1;
191
192         d_printf("%s", ctime(&t));
193         return 0;
194 }