b5a1db62ac8801a0f369b08d7bff36a7a58be814
[public/netxms.git] / src / snmp / nxmibc / nxmibc.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS MIB compiler
4 ** Copyright (C) 2005-2012 Victor Kirhenshtein
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 ** File: nxmibc.cpp
21 **
22 **/
23
24 #include "nxmibc.h"
25
26 #ifdef _WIN32
27 #include <conio.h>
28 #endif
29
30 /**
31 * Severity codes
32 */
33 #define MIBC_INFO 0
34 #define MIBC_WARNING 1
35 #define MIBC_ERROR 2
36
37 /**
38 * Externals
39 */
40 int ParseMIBFiles(int nNumFiles, char **ppszFileList, SNMP_MIBObject **ppRoot);
41
42 /**
43 * Static data
44 */
45 static char m_szOutFile[MAX_PATH] = "netxms.mib";
46 static int m_iNumFiles = 0;
47 static char **m_ppFileList = NULL;
48 static bool s_pauseBeforeExit = false;
49
50 /**
51 * Errors
52 */
53 static struct
54 {
55 int nSeverity;
56 const TCHAR *pszText;
57 } m_errorList[] =
58 {
59 { MIBC_INFO, _T("Operation completed successfully") },
60 { MIBC_ERROR, _T("Import symbol \"%hs\" unresolved") },
61 { MIBC_ERROR, _T("Import module \"%hs\" unresolved") },
62 { MIBC_ERROR, _T("Parser error - %hs in line %d") },
63 { MIBC_ERROR, _T("Cannot open input file (%hs)") },
64 { MIBC_ERROR, _T("Cannot resolve symbol %hs") },
65 { MIBC_WARNING, _T("Cannot resolve data type \"%hs\" for object \"%hs\"") }
66 };
67
68 /**
69 * Pause if needed
70 */
71 static void Pause()
72 {
73 if (s_pauseBeforeExit)
74 {
75 #ifdef _WIN32
76 _tprintf(_T("Press any key to continue...\n"));
77 _getch();
78 #else
79 _tprintf(_T("Press ENTER to continue...\n"));
80 char temp[256];
81 fgets(temp, 255, stdin);
82 #endif
83 }
84 }
85
86 /**
87 * Display error text and abort compilation
88 */
89 extern "C" void Error(int nError, char *pszModule, ...)
90 {
91 va_list args;
92 static const TCHAR *severityText[] = { _T("INFO"), _T("WARNING"), _T("ERROR") };
93
94 _tprintf(_T("%hs: %s %03d: "), pszModule, severityText[m_errorList[nError].nSeverity], nError);
95 va_start(args, pszModule);
96 _vtprintf(m_errorList[nError].pszText, args);
97 va_end(args);
98 _tprintf(_T("\n"));
99 if (m_errorList[nError].nSeverity == MIBC_ERROR)
100 {
101 Pause();
102 exit(1);
103 }
104 }
105
106 /**
107 * Display help and exit
108 */
109 static void Help()
110 {
111 _tprintf(_T("Usage:\n\n")
112 _T("nxmibc [options] source1 ... sourceN\n\n")
113 _T("Valid options:\n")
114 _T(" -d <dir> : Include all MIB files from given directory to compilation\n")
115 _T(" -r : Scan sub-directories \n")
116 _T(" -e <ext> : Specify file extensions (default extension: \"txt\") \n")
117 _T(" -o <file> : Set output file name (default is netxms.mib)\n")
118 _T(" -P : Pause before exit\n")
119 _T(" -s : Strip descriptions from MIB objects\n")
120 _T(" -z : Compress output file\n")
121 _T("\n"));
122 exit(0);
123 }
124
125 /**
126 * Add file to compilation list
127 */
128 static void AddFileToList(char *pszFile)
129 {
130 m_ppFileList = (char **)realloc(m_ppFileList, sizeof(char *) * (m_iNumFiles + 1));
131 m_ppFileList[m_iNumFiles++] = strdup(pszFile);
132 }
133
134 /**
135 * Scan directory for MIB files
136 */
137 static void ScanDirectory(const char *pszPath, const char *extensions, bool recursive)
138 {
139 DIR *pDir;
140 struct dirent *pFile;
141 char szBuffer[MAX_PATH];
142
143 pDir = opendir(pszPath);
144 if (pDir != NULL)
145 {
146 while(1)
147 {
148 pFile = readdir(pDir);
149 if (pFile == NULL)
150 break;
151 if (strcmp(pFile->d_name, ".") && strcmp(pFile->d_name, ".."))
152 {
153 snprintf(szBuffer, MAX_PATH, "%s" FS_PATH_SEPARATOR_A "%s", pszPath, pFile->d_name);
154 if (recursive && pFile->d_type == DT_DIR)
155 ScanDirectory(szBuffer, extensions, recursive);
156 else
157 {
158 char *extension = strrchr(pFile->d_name, '.');
159 if ((extension != NULL) && (strstr(extensions, extension) != NULL))
160 AddFileToList(szBuffer);
161 }
162 }
163 }
164 closedir(pDir);
165 }
166 }
167
168 /**
169 * Entry point
170 */
171 int main(int argc, char *argv[])
172 {
173 char paths[24][MAX_PATH];
174 char extensions[64] = ".txt ";
175 bool recursive = false;
176 bool scanDir = false;
177 SNMP_MIBObject *pRoot;
178 DWORD dwFlags = 0, dwRet;
179 int i, ch, rc = 0;
180
181 InitNetXMSProcess(true);
182
183 _tprintf(_T("NetXMS MIB Compiler Version ") NETXMS_VERSION_STRING _T(" (") NETXMS_BUILD_TAG _T(")\n")
184 _T("Copyright (c) 2005-2017 Raden Solutions\n\n"));
185
186 // Parse command line
187 opterr = 1;
188 int index = 0;
189 while((ch = getopt(argc, argv, "rd:ho:e:Psz")) != -1)
190 {
191 switch(ch)
192 {
193 case 'e':
194 {
195 char buffer[8];
196 snprintf(buffer, 8, ".%s ", optarg);
197 strcat(extensions, buffer);
198 }
199 break;
200 case 'h': // Display help and exit
201 Help();
202 break;
203 case 'd':
204 {
205 char buffer[MAX_PATH];
206 strncpy(paths[index], optarg, MAX_PATH);
207 scanDir = true;
208 index++;
209 }
210 break;
211 case 'o':
212 strncpy(m_szOutFile, optarg, MAX_PATH);
213 m_szOutFile[MAX_PATH - 1] = 0;
214 break;
215 case 'P':
216 s_pauseBeforeExit = true;
217 break;
218 case 'r':
219 recursive = true;
220 break;
221 case 's':
222 dwFlags |= SMT_SKIP_DESCRIPTIONS;
223 break;
224 case 'z':
225 dwFlags |= SMT_COMPRESS_DATA;
226 break;
227 case '?':
228 return 255;
229 default:
230 break;
231 }
232 }
233
234 if (scanDir)
235 {
236 for(int i = 0; i < index; i++)
237 {
238 ScanDirectory(paths[i], extensions, recursive);
239 }
240 }
241
242 for(i = optind; i < argc; i++)
243 AddFileToList(argv[i]);
244
245 if (m_iNumFiles > 0)
246 {
247 ParseMIBFiles(m_iNumFiles, m_ppFileList, &pRoot);
248
249 if (pRoot != NULL)
250 {
251 #ifdef UNICODE
252 WCHAR *wname = WideStringFromMBString(m_szOutFile);
253 dwRet = SNMPSaveMIBTree(wname, pRoot, dwFlags);
254 free(wname);
255 #else
256 dwRet = SNMPSaveMIBTree(m_szOutFile, pRoot, dwFlags);
257 #endif
258 delete pRoot;
259 if (dwRet != SNMP_ERR_SUCCESS)
260 {
261 _tprintf(_T("ERROR: Cannot save output file %hs (%s)\n"), m_szOutFile, SNMPGetErrorText(dwRet));
262 rc = 1;
263 }
264 }
265 }
266 else
267 {
268 _tprintf(_T("ERROR: No source files given\n"));
269 rc = 1;
270 }
271
272 Pause();
273 return rc;
274 }