67ed8bfb941e3f5c28dff44eda8d05f94601becd
[public/netxms.git] / src / server / tools / nxupload / nxupload.cpp
1 /*
2 ** nxupload - command line tool used to upload files to NetXMS agent
3 ** Copyright (C) 2004 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** $module: nxupload.cpp
20 **
21 **/
22
23 #include <nms_common.h>
24 #include <nms_agent.h>
25 #include <nms_util.h>
26 #include <nxclapi.h>
27 #include <nxsrvapi.h>
28
29 #ifndef _WIN32
30 #include <netdb.h>
31 #endif
32
33
34 //
35 // Do agent upgrade
36 //
37
38 static int UpgradeAgent(AgentConnection &conn, TCHAR *pszPkgName, BOOL bVerbose)
39 {
40 DWORD dwError;
41 int i;
42 BOOL bConnected = FALSE;
43
44 dwError = conn.StartUpgrade(pszPkgName);
45 if (dwError == ERR_SUCCESS)
46 {
47 conn.Disconnect();
48
49 if (bVerbose)
50 {
51 printf("Agent upgrade started, waiting for completion...\n"
52 "[............................................................]\r[");
53 fflush(stdout);
54 for(i = 0; i < 120; i += 2)
55 {
56 ThreadSleep(2);
57 putc('*', stdout);
58 fflush(stdout);
59 if ((i % 20 == 0) && (i > 30))
60 {
61 if (conn.Connect(FALSE))
62 {
63 bConnected = TRUE;
64 break; // Connected successfully
65 }
66 }
67 }
68 putc('\n', stdout);
69 }
70 else
71 {
72 ThreadSleep(20);
73 for(i = 20; i < 120; i += 20)
74 {
75 ThreadSleep(20);
76 if (conn.Connect(FALSE))
77 {
78 bConnected = TRUE;
79 break; // Connected successfully
80 }
81 }
82 }
83
84 // Last attempt to reconnect
85 if (!bConnected)
86 bConnected = conn.Connect(bVerbose);
87
88 if (bConnected && bVerbose)
89 {
90 printf("Successfully established connection to agent after upgrade\n");
91 }
92 else
93 {
94 fprintf(stderr, "Failed to establish connection to the agent after upgrade\n");
95 }
96 }
97 else
98 {
99 if (bVerbose)
100 fprintf(stderr, "%d: %s\n", dwError, AgentErrorCodeToText(dwError));
101 }
102
103 return bConnected ? 0 : 1;
104 }
105
106
107 //
108 // Startup
109 //
110
111 int main(int argc, char *argv[])
112 {
113 char *eptr;
114 BOOL bStart = TRUE, bVerbose = TRUE, bUpgrade = TRUE;
115 int i, ch, iExitCode = 3;
116 int iAuthMethod = AUTH_NONE;
117 WORD wPort = AGENT_LISTEN_PORT;
118 DWORD dwAddr, dwTimeout = 3000;
119 char szSecret[MAX_SECRET_LENGTH] = "";
120 INT64 nElapsedTime;
121
122 // Parse command line
123 opterr = 1;
124 while((ch = getopt(argc, argv, "a:hp:qs:uvw:")) != -1)
125 {
126 switch(ch)
127 {
128 case 'h': // Display help and exit
129 printf("Usage: nxupload [<options>] <host> <file>\n"
130 "Valid options are:\n"
131 " -a <auth> : Authentication method. Valid methods are \"none\",\n"
132 " \"plain\", \"md5\" and \"sha1\". Default is \"none\".\n"
133 " -h : Display help and exit.\n"
134 " -p <port> : Specify agent's port number. Default is %d.\n"
135 " -q : Quiet mode.\n"
136 " -s <secret> : Specify shared secret for authentication.\n"
137 " -u : Start agent upgrade from uploaded package.\n"
138 " -v : Display version and exit.\n"
139 " -w <seconds> : Specify command timeout (default is 3 seconds)\n"
140 "\n", wPort);
141 bStart = FALSE;
142 break;
143 case 'a': // Auth method
144 if (!strcmp(optarg, "none"))
145 iAuthMethod = AUTH_NONE;
146 else if (!strcmp(optarg, "plain"))
147 iAuthMethod = AUTH_PLAINTEXT;
148 else if (!strcmp(optarg, "md5"))
149 iAuthMethod = AUTH_MD5_HASH;
150 else if (!strcmp(optarg, "sha1"))
151 iAuthMethod = AUTH_SHA1_HASH;
152 else
153 {
154 printf("Invalid authentication method \"%s\"\n", optarg);
155 bStart = FALSE;
156 }
157 break;
158 case 'p': // Port number
159 i = strtol(optarg, &eptr, 0);
160 if ((*eptr != 0) || (i < 0) || (i > 65535))
161 {
162 printf("Invalid port number \"%s\"\n", optarg);
163 bStart = FALSE;
164 }
165 else
166 {
167 wPort = (WORD)i;
168 }
169 break;
170 case 'q': // Quiet mode
171 bVerbose = FALSE;
172 break;
173 case 's': // Shared secret
174 strncpy(szSecret, optarg, MAX_SECRET_LENGTH - 1);
175 break;
176 case 'u': // Upgrade agent
177 bUpgrade = TRUE;
178 break;
179 case 'v': // Print version and exit
180 printf("NetXMS UPLOAD command-line utility Version " NETXMS_VERSION_STRING "\n");
181 bStart = FALSE;
182 break;
183 case 'w': // Command timeout
184 i = strtol(optarg, &eptr, 0);
185 if ((*eptr != 0) || (i < 1) || (i > 120))
186 {
187 printf("Invalid timeout \"%s\"\n", optarg);
188 bStart = FALSE;
189 }
190 else
191 {
192 dwTimeout = (DWORD)i * 1000; // Convert to milliseconds
193 }
194 break;
195 case '?':
196 bStart = FALSE;
197 break;
198 default:
199 break;
200 }
201 }
202
203 // Check parameter correctness
204 if (bStart)
205 {
206 if (argc - optind < 2)
207 {
208 if (bVerbose)
209 printf("Required argument(s) missing.\nUse nxupload -h to get complete command line syntax.\n");
210 bStart = FALSE;
211 }
212 else if ((iAuthMethod != AUTH_NONE) && (szSecret[0] == 0))
213 {
214 if (bVerbose)
215 fprintf(stderr, "Shared secret not specified or empty\n");
216 bStart = FALSE;
217 }
218
219 // If everything is ok, start communications
220 if (bStart)
221 {
222 struct hostent *hs;
223
224 // Initialize WinSock
225 #ifdef _WIN32
226 WSADATA wsaData;
227 WSAStartup(2, &wsaData);
228 #endif
229
230 // Resolve hostname
231 hs = gethostbyname(argv[optind]);
232 if (hs != NULL)
233 {
234 memcpy(&dwAddr, hs->h_addr, sizeof(DWORD));
235 }
236 else
237 {
238 dwAddr = inet_addr(argv[optind]);
239 }
240 if ((dwAddr == 0) || (dwAddr == INADDR_NONE))
241 {
242 if (bVerbose)
243 fprintf(stderr, "Invalid host name or address specified\n");
244 }
245 else
246 {
247 AgentConnection conn(dwAddr, wPort, iAuthMethod, szSecret);
248
249 conn.SetCommandTimeout(dwTimeout);
250 if (conn.Connect(bVerbose))
251 {
252 DWORD dwError;
253
254 nElapsedTime = GetCurrentTimeMs();
255 dwError = conn.UploadFile(argv[optind + 1]);
256 nElapsedTime = GetCurrentTimeMs() - nElapsedTime;
257 if (bVerbose)
258 {
259 if (dwError == ERR_SUCCESS)
260 {
261 QWORD qwBytes;
262
263 qwBytes = FileSize(argv[optind + 1]);
264 printf("File transferred successfully\n"
265 #ifdef _WIN32
266 "%I64u"
267 #else
268 "%llu"
269 #endif
270 " bytes in %d.%03d seconds (%.2f KB/sec)\n",
271 qwBytes, (long)(nElapsedTime / 1000),
272 (long)(nElapsedTime % 1000),
273 ((double)((INT64)qwBytes / 1024) / (double)nElapsedTime) * 1000);
274 }
275 else
276 {
277 fprintf(stderr, "%d: %s\n", dwError, AgentErrorCodeToText(dwError));
278 }
279 }
280
281 if (bUpgrade && (dwError == RCC_SUCCESS))
282 {
283 iExitCode = UpgradeAgent(conn, argv[optind + 1], bVerbose);
284 }
285 else
286 {
287 iExitCode = (dwError == ERR_SUCCESS) ? 0 : 1;
288 }
289 conn.Disconnect();
290 }
291 else
292 {
293 iExitCode = 2;
294 }
295 }
296 }
297 }
298
299 return iExitCode;
300 }