392c3570db6e6774c4be2728081216eb914a093c
[public/netxms.git] / src / server / tools / nxdbmgr / nxdbmgr.cpp
1 /*
2 ** nxdbmgr - NetXMS database manager
3 ** Copyright (C) 2004-2013 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 ** File: nxdbmgr.cpp
20 **
21 **/
22
23 #include "nxdbmgr.h"
24 #include <nxconfig.h>
25
26 #ifdef _WIN32
27 #include <conio.h>
28 #endif
29
30 /**
31 * Global variables
32 */
33 DB_HANDLE g_hCoreDB;
34 BOOL g_bIgnoreErrors = FALSE;
35 BOOL g_bTrace = FALSE;
36 bool g_isGuiMode = false;
37 bool g_checkData = false;
38 int g_iSyntax;
39 const TCHAR *g_pszTableSuffix = _T("");
40 const TCHAR *g_pszSqlType[6][3] =
41 {
42 { _T("text"), _T("text"), _T("bigint") }, // MySQL
43 { _T("text"), _T("varchar(4000)"), _T("bigint") }, // PostgreSQL
44 { _T("text"), _T("varchar(4000)"), _T("bigint") }, // Microsoft SQL
45 { _T("clob"), _T("varchar(4000)"), _T("number(20)") }, // Oracle
46 { _T("varchar"), _T("varchar(4000)"), _T("number(20)") }, // SQLite
47 { _T("long varchar"), _T("varchar(4000)"), _T("bigint") } // DB/2
48 };
49
50 /**
51 * Static data
52 */
53 static char m_szCodePage[MAX_PATH] = ICONV_DEFAULT_CODEPAGE_A;
54 static TCHAR s_encryptedDbPassword[MAX_DB_STRING] = _T("");
55 static TCHAR s_dbDriver[MAX_PATH] = _T("");
56 static TCHAR s_dbDrvParams[MAX_PATH] = _T("");
57 static TCHAR s_dbServer[MAX_PATH] = _T("127.0.0.1");
58 static TCHAR s_dbLogin[MAX_DB_LOGIN] = _T("netxms");
59 static TCHAR s_dbPassword[MAX_DB_PASSWORD] = _T("");
60 static TCHAR s_dbName[MAX_DB_NAME] = _T("netxms_db");
61 static TCHAR s_dbSchema[MAX_DB_NAME] = _T("");
62 static NX_CFG_TEMPLATE m_cfgTemplate[] =
63 {
64 { _T("CodePage"), CT_MB_STRING, 0, 0, MAX_PATH, 0, m_szCodePage },
65 { _T("CreateCrashDumps"), CT_IGNORE, 0, 0, 0, 0, NULL },
66 { _T("DBDriver"), CT_STRING, 0, 0, MAX_PATH, 0, s_dbDriver },
67 { _T("DBDrvParams"), CT_STRING, 0, 0, MAX_PATH, 0, s_dbDrvParams },
68 { _T("DBEncryptedPassword"), CT_STRING, 0, 0, MAX_DB_STRING, 0, s_encryptedDbPassword },
69 { _T("DBLogin"), CT_STRING, 0, 0, MAX_DB_LOGIN, 0, s_dbLogin },
70 { _T("DBName"), CT_STRING, 0, 0, MAX_DB_NAME, 0, s_dbName },
71 { _T("DBPassword"), CT_STRING, 0, 0, MAX_DB_PASSWORD, 0, s_dbPassword },
72 { _T("DBSchema"), CT_STRING, 0, 0, MAX_PATH, 0, s_dbSchema },
73 { _T("DBServer"), CT_STRING, 0, 0, MAX_PATH, 0, s_dbServer },
74 { _T("DataDirectory"), CT_IGNORE, 0, 0, 0, 0, NULL },
75 { _T("DumpDirectory"), CT_IGNORE, 0, 0, 0, 0, NULL },
76 { _T("LogFailedSQLQueries"), CT_IGNORE, 0, 0, 0, 0, NULL },
77 { _T("LogFile"), CT_IGNORE, 0, 0, 0, 0, NULL },
78 { _T("Module"), CT_IGNORE, 0, 0, 0, 0, NULL },
79 { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL }
80 };
81 static BOOL m_bForce = FALSE;
82
83 /**
84 * Show query if trace mode is ON
85 */
86 void ShowQuery(const TCHAR *pszQuery)
87 {
88 WriteToTerminalEx(_T("\x1b[1m>>> \x1b[32;1m%s\x1b[0m\n"), pszQuery);
89 }
90
91 /**
92 * Get Yes or No answer from keyboard
93 */
94 bool GetYesNo(const TCHAR *format, ...)
95 {
96 va_list args;
97
98 if (g_isGuiMode)
99 {
100 if (m_bForce)
101 return true;
102
103 TCHAR message[4096];
104 va_start(args, format);
105 _vsntprintf(message, 4096, format, args);
106 va_end(args);
107
108 #ifdef _WIN32
109 return MessageBox(NULL, message, _T("NetXMS Database Manager"), MB_YESNO | MB_ICONQUESTION) == IDYES;
110 #else
111 return false;
112 #endif
113 }
114 else
115 {
116 va_start(args, format);
117 _vtprintf(format, args);
118 va_end(args);
119 _tprintf(_T(" (Y/N) "));
120
121 if (m_bForce)
122 {
123 _tprintf(_T("Y\n"));
124 return true;
125 }
126 else
127 {
128 #ifdef _WIN32
129 int ch;
130
131 while(1)
132 {
133 ch = _getch();
134 if ((ch == 'y') || (ch == 'Y'))
135 {
136 _tprintf(_T("Y\n"));
137 return true;
138 }
139 if ((ch == 'n') || (ch == 'N'))
140 {
141 _tprintf(_T("N\n"));
142 return false;
143 }
144 }
145 #else
146 TCHAR szBuffer[16];
147
148 fflush(stdout);
149 _fgetts(szBuffer, 16, stdin);
150 StrStrip(szBuffer);
151 return ((szBuffer[0] == 'y') || (szBuffer[0] == 'Y'));
152 #endif
153 }
154 }
155 }
156
157 /**
158 * Execute SQL SELECT query and print error message on screen if query failed
159 */
160 DB_RESULT SQLSelect(const TCHAR *pszQuery)
161 {
162 DB_RESULT hResult;
163 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
164
165 if (g_bTrace)
166 ShowQuery(pszQuery);
167
168 hResult = DBSelectEx(g_hCoreDB, pszQuery, errorText);
169 if (hResult == NULL)
170 WriteToTerminalEx(_T("SQL query failed (%s):\n\x1b[33;1m%s\x1b[0m\n"), errorText, pszQuery);
171 return hResult;
172 }
173
174 /**
175 * Execute SQL SELECT query via DBAsyncSelect and print error message on screen if query failed
176 */
177 DB_ASYNC_RESULT SQLAsyncSelect(const TCHAR *pszQuery)
178 {
179 DB_ASYNC_RESULT hResult;
180 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
181
182 if (g_bTrace)
183 ShowQuery(pszQuery);
184
185 hResult = DBAsyncSelectEx(g_hCoreDB, pszQuery, errorText);
186 if (hResult == NULL)
187 WriteToTerminalEx(_T("SQL query failed (%s):\n\x1b[33;1m%s\x1b[0m\n"), errorText, pszQuery);
188 return hResult;
189 }
190
191 /**
192 * Execute SQL query and print error message on screen if query failed
193 */
194 BOOL SQLQuery(const TCHAR *pszQuery)
195 {
196 BOOL bResult;
197 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
198
199 if (*pszQuery == 0)
200 return TRUE;
201
202 String query(pszQuery);
203
204 query.replace(_T("$SQL:TEXT"), g_pszSqlType[g_iSyntax][SQL_TYPE_TEXT]);
205 query.replace(_T("$SQL:TXT4K"), g_pszSqlType[g_iSyntax][SQL_TYPE_TEXT4K]);
206 query.replace(_T("$SQL:INT64"), g_pszSqlType[g_iSyntax][SQL_TYPE_INT64]);
207
208 if (g_bTrace)
209 ShowQuery(query);
210
211 bResult = DBQueryEx(g_hCoreDB, (const TCHAR *)query, errorText);
212 if (!bResult)
213 WriteToTerminalEx(_T("SQL query failed (%s):\n\x1b[33;1m%s\x1b[0m\n"), errorText, (const TCHAR *)query);
214 return bResult;
215 }
216
217 /**
218 * Execute SQL batch
219 */
220 BOOL SQLBatch(const TCHAR *pszBatch)
221 {
222 String batch(pszBatch);
223 TCHAR *pszBuffer, *pszQuery, *ptr;
224 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
225 BOOL bRet = TRUE;
226 TCHAR table[128], column[128];
227
228 batch.replace(_T("$SQL:TEXT"), g_pszSqlType[g_iSyntax][SQL_TYPE_TEXT]);
229 batch.replace(_T("$SQL:TXT4K"), g_pszSqlType[g_iSyntax][SQL_TYPE_TEXT4K]);
230 batch.replace(_T("$SQL:INT64"), g_pszSqlType[g_iSyntax][SQL_TYPE_INT64]);
231
232 pszQuery = pszBuffer = batch.getBuffer();
233 while(1)
234 {
235 ptr = _tcschr(pszQuery, _T('\n'));
236 if (ptr != NULL)
237 *ptr = 0;
238 if (!_tcscmp(pszQuery, _T("<END>")))
239 break;
240
241 if (_stscanf(pszQuery, _T("ALTER TABLE %128s DROP COLUMN %128s"), table, column) == 2)
242 {
243 if (!SQLDropColumn(table, column))
244 {
245 WriteToTerminalEx(_T("Cannot drop column \x1b[37;1m%s.%s\x1b[0m\n"), table, column);
246 if (!g_bIgnoreErrors)
247 {
248 bRet = FALSE;
249 break;
250 }
251 }
252 }
253 else
254 {
255 if (g_bTrace)
256 ShowQuery(pszQuery);
257
258 if (!DBQueryEx(g_hCoreDB, pszQuery, errorText))
259 {
260 WriteToTerminalEx(_T("SQL query failed (%s):\n\x1b[33;1m%s\x1b[0m\n"), errorText, pszQuery);
261 if (!g_bIgnoreErrors)
262 {
263 bRet = FALSE;
264 break;
265 }
266 }
267 }
268
269 ptr++;
270 pszQuery = ptr;
271 }
272 return bRet;
273 }
274
275 /**
276 * Drop column from the table
277 */
278 BOOL SQLDropColumn(const TCHAR *table, const TCHAR *column)
279 {
280 TCHAR query[1024];
281 DB_RESULT hResult;
282 BOOL success = FALSE;
283
284 if (g_iSyntax != DB_SYNTAX_SQLITE)
285 {
286 _sntprintf(query, 1024, _T("ALTER TABLE %s DROP COLUMN %s"), table, column);
287 success = SQLQuery(query);
288 }
289 else
290 {
291 _sntprintf(query, 1024, _T("PRAGMA TABLE_INFO('%s')"), table);
292 hResult = SQLSelect(query);
293 if (hResult != NULL)
294 {
295 int rows = DBGetNumRows(hResult);
296 const int blen = 2048;
297 TCHAR buffer[blen];
298 // Intermediate buffers for SQLs
299 TCHAR columnList[1024], createList[1024];
300 // TABLE_INFO() columns
301 TCHAR tabColName[128], tabColType[64], tabColNull[10], tabColDefault[128];
302 columnList[0] = createList[0] = _T('\0');
303 for (int i = 0; i < rows; i++)
304 {
305 DBGetField(hResult, i, 1, tabColName, 128);
306 DBGetField(hResult, i, 2, tabColType, 64);
307 DBGetField(hResult, i, 3, tabColNull, 10);
308 DBGetField(hResult, i, 4, tabColDefault, 128);
309 if (_tcsnicmp(tabColName, column, 128))
310 {
311 _tcscat(columnList, tabColName);
312 if (columnList[0] != _T('\0'))
313 _tcscat(columnList, _T(","));
314 _tcscat(createList, tabColName);
315 _tcscat(createList, tabColType);
316 if (tabColDefault[0] != _T('\0'))
317 {
318 _tcscat(createList, _T("DEFAULT "));
319 _tcscat(createList, tabColDefault);
320 }
321 if (tabColNull[0] == _T('1'))
322 _tcscat(createList, _T(" NOT NULL"));
323 _tcscat(createList, _T(","));
324 }
325 }
326 DBFreeResult(hResult);
327 if (rows > 0)
328 {
329 int cllen = (int)_tcslen(columnList);
330 if (cllen > 0 && columnList[cllen - 1] == _T(','))
331 columnList[cllen - 1] = _T('\0');
332 // TODO: figure out if SQLite transactions will work here
333 _sntprintf(buffer, blen, _T("CREATE TABLE %s__backup__ (%s)"), table, columnList);
334 CHK_EXEC(SQLQuery(buffer));
335 _sntprintf(buffer, blen, _T("INSERT INTO %s__backup__ (%s) SELECT %s FROM %s"),
336 table, columnList, columnList, table);
337 CHK_EXEC(SQLQuery(buffer));
338 _sntprintf(buffer, blen, _T("DROP TABLE %s"), table);
339 CHK_EXEC(SQLQuery(buffer));
340 _sntprintf(buffer, blen, _T("ALTER TABLE %s__backup__ RENAME to %s"), table, table);
341 CHK_EXEC(SQLQuery(buffer));
342 success = TRUE;
343 }
344 }
345 }
346
347 // TODO: preserve indices and constraints??
348
349 return success;
350 }
351
352 /**
353 * Read string value from metadata table
354 */
355 BOOL MetaDataReadStr(const TCHAR *pszVar, TCHAR *pszBuffer, int iBufSize, const TCHAR *pszDefault)
356 {
357 DB_RESULT hResult;
358 TCHAR szQuery[256];
359 BOOL bSuccess = FALSE;
360
361 nx_strncpy(pszBuffer, pszDefault, iBufSize);
362 if (_tcslen(pszVar) > 127)
363 return FALSE;
364
365 _sntprintf(szQuery, 256, _T("SELECT var_value FROM metadata WHERE var_name='%s'"), pszVar);
366 hResult = SQLSelect(szQuery);
367 if (hResult == NULL)
368 return FALSE;
369
370 if (DBGetNumRows(hResult) > 0)
371 {
372 DBGetField(hResult, 0, 0, pszBuffer, iBufSize);
373 bSuccess = TRUE;
374 }
375
376 DBFreeResult(hResult);
377 return bSuccess;
378 }
379
380 /**
381 * Read string value from configuration table
382 */
383 BOOL ConfigReadStr(const TCHAR *pszVar, TCHAR *pszBuffer, int iBufSize, const TCHAR *pszDefault)
384 {
385 DB_RESULT hResult;
386 TCHAR szQuery[256];
387 BOOL bSuccess = FALSE;
388
389 nx_strncpy(pszBuffer, pszDefault, iBufSize);
390 if (_tcslen(pszVar) > 127)
391 return FALSE;
392
393 _sntprintf(szQuery, 256, _T("SELECT var_value FROM config WHERE var_name='%s'"), pszVar);
394 hResult = SQLSelect(szQuery);
395 if (hResult == NULL)
396 return FALSE;
397
398 if (DBGetNumRows(hResult) > 0)
399 {
400 DBGetField(hResult, 0, 0, pszBuffer, iBufSize);
401 bSuccess = TRUE;
402 }
403
404 DBFreeResult(hResult);
405 return bSuccess;
406 }
407
408
409 //
410 // Read integer value from configuration table
411 //
412
413 int ConfigReadInt(const TCHAR *pszVar, int iDefault)
414 {
415 TCHAR szBuffer[64];
416
417 if (ConfigReadStr(pszVar, szBuffer, 64, _T("")))
418 return _tcstol(szBuffer, NULL, 0);
419 else
420 return iDefault;
421 }
422
423
424 //
425 // Read unsigned long value from configuration table
426 //
427
428 DWORD ConfigReadULong(const TCHAR *pszVar, DWORD dwDefault)
429 {
430 TCHAR szBuffer[64];
431
432 if (ConfigReadStr(pszVar, szBuffer, 64, _T("")))
433 return _tcstoul(szBuffer, NULL, 0);
434 else
435 return dwDefault;
436 }
437
438
439 //
440 // Check that database has correct schema version and is not locked
441 //
442
443 BOOL ValidateDatabase()
444 {
445 DB_RESULT hResult;
446 LONG nVersion = 0;
447 BOOL bLocked = FALSE;
448 TCHAR szLockStatus[MAX_DB_STRING], szLockInfo[MAX_DB_STRING];
449
450 // Get database format version
451 nVersion = DBGetSchemaVersion(g_hCoreDB);
452 if (nVersion < DB_FORMAT_VERSION)
453 {
454 _tprintf(_T("Your database has format version %d, this tool is compiled for version %d.\nUse \"upgrade\" command to upgrade your database first.\n"),
455 nVersion, DB_FORMAT_VERSION);
456 return FALSE;
457 }
458 else if (nVersion > DB_FORMAT_VERSION)
459 {
460 _tprintf(_T("Your database has format version %d, this tool is compiled for version %d.\n")
461 _T("You need to upgrade your server before using this database.\n"),
462 nVersion, DB_FORMAT_VERSION);
463 return FALSE;
464 }
465
466 // Check if database is locked
467 hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBLockStatus'"));
468 if (hResult != NULL)
469 {
470 if (DBGetNumRows(hResult) > 0)
471 {
472 DBGetField(hResult, 0, 0, szLockStatus, MAX_DB_STRING);
473 bLocked = _tcscmp(szLockStatus, _T("UNLOCKED"));
474 }
475 DBFreeResult(hResult);
476
477 if (bLocked)
478 {
479 hResult = DBSelect(g_hCoreDB, _T("SELECT var_value FROM config WHERE var_name='DBLockInfo'"));
480 if (hResult != NULL)
481 {
482 if (DBGetNumRows(hResult) > 0)
483 {
484 DBGetField(hResult, 0, 0, szLockInfo, MAX_DB_STRING);
485 }
486 DBFreeResult(hResult);
487 }
488 }
489 }
490
491 if (bLocked)
492 {
493 _tprintf(_T("Database is locked by server %s [%s]\n"), szLockStatus, szLockInfo);
494 return FALSE;
495 }
496
497 return TRUE;
498 }
499
500
501 //
502 // Startup
503 //
504
505 int main(int argc, char *argv[])
506 {
507 BOOL bStart = TRUE, bForce = FALSE, bQuiet = FALSE, bReplaceValue = TRUE;
508 int ch;
509 TCHAR szConfigFile[MAX_PATH] = DEFAULT_CONFIG_FILE;
510 #ifdef _WIN32
511 HKEY hKey;
512 DWORD dwSize;
513 #else
514 TCHAR *pszEnv;
515 #endif
516
517 InitThreadLibrary();
518
519 // Check for alternate config file location
520 #ifdef _WIN32
521 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\NetXMS\\Server"), 0,
522 KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
523 {
524 dwSize = MAX_PATH * sizeof(TCHAR);
525 RegQueryValueEx(hKey, _T("ConfigFile"), NULL, NULL, (BYTE *)szConfigFile, &dwSize);
526 RegCloseKey(hKey);
527 }
528 #else
529 pszEnv = _tgetenv(_T("NETXMSD_CONFIG"));
530 if (pszEnv != NULL)
531 nx_strncpy(szConfigFile, pszEnv, MAX_PATH);
532 #endif
533
534 // Parse command line
535 opterr = 1;
536 while((ch = getopt(argc, argv, "c:dfGhIMNqtvX")) != -1)
537 {
538 switch(ch)
539 {
540 case 'h': // Display help and exit
541 _tprintf(_T("NetXMS Database Manager Version ") NETXMS_VERSION_STRING _T("\n\n"));
542 _tprintf(_T("Usage: nxdbmgr [<options>] <command>\n")
543 _T("Valid commands are:\n")
544 _T(" batch <file> : Run SQL batch file\n")
545 _T(" check : Check database for errors\n")
546 _T(" export <file> : Export database to file\n")
547 _T(" get <name> : Get value of server configuration variable\n")
548 _T(" import <file> : Import database from file\n")
549 _T(" init <file> : Initialize database\n")
550 _T(" reindex : Reindex database\n")
551 _T(" set <name> <value> : Set value of server configuration variable\n")
552 _T(" unlock : Forced database unlock\n")
553 _T(" upgrade : Upgrade database to new version\n")
554 _T(" resetadmin : Unlock user \"admin\" and reset password to default (\"netxms\")\n")
555 _T("Valid options are:\n")
556 _T(" -c <config> : Use alternate configuration file. Default is ") DEFAULT_CONFIG_FILE _T("\n")
557 _T(" -d : Check collected data (may take very long time).\n")
558 _T(" -f : Force repair - do not ask for confirmation.\n")
559 #ifdef _WIN32
560 _T(" -G : GUI mode.\n")
561 #endif
562 _T(" -h : Display help and exit.\n")
563 _T(" -I : MySQL only - specify TYPE=InnoDB for new tables.\n")
564 _T(" -M : MySQL only - specify TYPE=MyISAM for new tables.\n")
565 _T(" -N : Do not replace existing configuration value (\"set\" command only).\n")
566 _T(" -q : Quiet mode (don't show startup banner).\n")
567 _T(" -t : Enable trace mode (show executed SQL queries).\n")
568 _T(" -v : Display version and exit.\n")
569 _T(" -X : Ignore SQL errors when upgrading (USE WITH CAUTION!!!)\n")
570 _T("\n"));
571 bStart = FALSE;
572 break;
573 case 'v': // Print version and exit
574 _tprintf(_T("NetXMS Database Manager Version ") NETXMS_VERSION_STRING _T("\n\n"));
575 bStart = FALSE;
576 break;
577 case 'c':
578 #ifdef UNICODE
579 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, szConfigFile, MAX_PATH);
580 szConfigFile[MAX_PATH - 1] = 0;
581 #else
582 nx_strncpy(szConfigFile, optarg, MAX_PATH);
583 #endif
584 break;
585 case 'd':
586 g_checkData = true;
587 break;
588 case 'f':
589 m_bForce = TRUE;
590 break;
591 case 'G':
592 g_isGuiMode = true;
593 break;
594 case 'N':
595 bReplaceValue = FALSE;
596 break;
597 case 'q':
598 bQuiet = TRUE;
599 break;
600 case 't':
601 g_bTrace = TRUE;
602 break;
603 case 'I':
604 g_pszTableSuffix = _T(" TYPE=InnoDB");
605 break;
606 case 'M':
607 g_pszTableSuffix = _T(" TYPE=MyISAM");
608 break;
609 case 'X':
610 g_bIgnoreErrors = TRUE;
611 break;
612 case '?':
613 bStart = FALSE;
614 break;
615 default:
616 break;
617 }
618 }
619
620 if (!bStart)
621 return 1;
622
623 if (!bQuiet)
624 _tprintf(_T("NetXMS Database Manager Version ") NETXMS_VERSION_STRING _T("\n\n"));
625
626 // Check parameter correctness
627 if (argc - optind == 0)
628 {
629 _tprintf(_T("Command missing. Type nxdbmgr -h for command line syntax.\n"));
630 return 1;
631 }
632 if (strcmp(argv[optind], "batch") &&
633 strcmp(argv[optind], "check") &&
634 strcmp(argv[optind], "export") &&
635 strcmp(argv[optind], "get") &&
636 strcmp(argv[optind], "import") &&
637 strcmp(argv[optind], "init") &&
638 strcmp(argv[optind], "reindex") &&
639 strcmp(argv[optind], "set") &&
640 strcmp(argv[optind], "unlock") &&
641 strcmp(argv[optind], "upgrade") &&
642 strcmp(argv[optind], "resetadmin"))
643 {
644 _tprintf(_T("Invalid command \"%hs\". Type nxdbmgr -h for command line syntax.\n"), argv[optind]);
645 return 1;
646 }
647 if (((!strcmp(argv[optind], "init") || !strcmp(argv[optind], "batch") || !strcmp(argv[optind], "export") || !strcmp(argv[optind], "import") || !strcmp(argv[optind], "get")) && (argc - optind < 2)) ||
648 (!strcmp(argv[optind], "set") && (argc - optind < 3)))
649 {
650 _tprintf(_T("Required command argument(s) missing\n"));
651 return 1;
652 }
653
654 // Read configuration file
655 #if !defined(_WIN32) && !defined(_NETWARE)
656 if (!_tcscmp(szConfigFile, _T("{search}")))
657 {
658 if (_taccess(PREFIX _T("/etc/netxmsd.conf"), 4) == 0)
659 {
660 _tcscpy(szConfigFile, PREFIX _T("/etc/netxmsd.conf"));
661 }
662 else if (_taccess(_T("/usr/etc/netxmsd.conf"), 4) == 0)
663 {
664 _tcscpy(szConfigFile, _T("/usr/etc/netxmsd.conf"));
665 }
666 else
667 {
668 _tcscpy(szConfigFile, _T("/etc/netxmsd.conf"));
669 }
670 }
671 #endif
672
673 Config *config = new Config();
674 if (!config->loadIniConfig(szConfigFile, _T("server")) || !config->parseTemplate(_T("server"), m_cfgTemplate))
675 {
676 _tprintf(_T("Error loading configuration file\n"));
677 return 2;
678 }
679 delete config;
680
681 // Decrypt password
682 if (s_encryptedDbPassword[0] != 0)
683 {
684 DecryptPassword(s_dbLogin, s_encryptedDbPassword, s_dbPassword);
685 }
686
687 #ifndef _WIN32
688 SetDefaultCodepage(m_szCodePage);
689 #endif
690
691 // Connect to database
692 if (!DBInit(0, 0))
693 {
694 _tprintf(_T("Unable to initialize database library\n"));
695 return 3;
696 }
697
698 DB_DRIVER driver = DBLoadDriver(s_dbDriver, s_dbDrvParams, false, NULL, NULL);
699 if (driver == NULL)
700 {
701 _tprintf(_T("Unable to load and initialize database driver \"%s\"\n"), s_dbDriver);
702 return 3;
703 }
704
705 TCHAR errorText[DBDRV_MAX_ERROR_TEXT];
706 g_hCoreDB = DBConnect(driver, s_dbServer, s_dbName, s_dbLogin, s_dbPassword, s_dbSchema, errorText);
707 if (g_hCoreDB == NULL)
708 {
709 _tprintf(_T("Unable to connect to database %s@%s as %s: %s\n"), s_dbName, s_dbServer, s_dbLogin, errorText);
710 DBUnloadDriver(driver);
711 return 4;
712 }
713
714 if (!strcmp(argv[optind], "init"))
715 {
716 InitDatabase(argv[optind + 1]);
717 }
718 else
719 {
720 // Get database syntax
721 g_iSyntax = DBGetSyntax(g_hCoreDB);
722 if (g_iSyntax == DB_SYNTAX_UNKNOWN)
723 {
724 _tprintf(_T("Unable to determine database syntax\n"));
725 DBDisconnect(g_hCoreDB);
726 DBUnloadDriver(driver);
727 return 5;
728 }
729
730 // Do requested operation
731 if (!strcmp(argv[optind], "batch"))
732 ExecSQLBatch(argv[optind + 1]);
733 else if (!strcmp(argv[optind], "check"))
734 CheckDatabase();
735 else if (!strcmp(argv[optind], "upgrade"))
736 UpgradeDatabase();
737 else if (!strcmp(argv[optind], "unlock"))
738 UnlockDatabase();
739 else if (!strcmp(argv[optind], "reindex"))
740 ReindexDatabase();
741 else if (!strcmp(argv[optind], "export"))
742 ExportDatabase(argv[optind + 1]);
743 else if (!strcmp(argv[optind], "import"))
744 ImportDatabase(argv[optind + 1]);
745 else if (!strcmp(argv[optind], "get"))
746 {
747 #ifdef UNICODE
748 WCHAR *var = WideStringFromMBString(argv[optind + 1]);
749 #else
750 char *var = argv[optind + 1];
751 #endif
752 TCHAR buffer[MAX_DB_STRING];
753 ConfigReadStr(var, buffer, MAX_DB_STRING, _T(""));
754 _tprintf(_T("%s\n"), buffer);
755 #ifdef UNICODE
756 free(var);
757 #endif
758 }
759 else if (!strcmp(argv[optind], "set"))
760 {
761 #ifdef UNICODE
762 WCHAR *var = WideStringFromMBString(argv[optind + 1]);
763 WCHAR *value = WideStringFromMBString(argv[optind + 2]);
764 #else
765 char *var = argv[optind + 1];
766 char *value = argv[optind + 2];
767 #endif
768 CreateConfigParam(var, value, 1, 0, bReplaceValue);
769 #ifdef UNICODE
770 free(var);
771 free(value);
772 #endif
773 }
774 else if (!strcmp(argv[optind], "resetadmin"))
775 {
776 ResetAdmin();
777 }
778 }
779
780 // Shutdown
781 DBDisconnect(g_hCoreDB);
782 DBUnloadDriver(driver);
783 return 0;
784 }