PageRenderTime 1452ms CodeModel.GetById 211ms app.highlight 598ms RepoModel.GetById 582ms app.codeStats 1ms

/deployment/configgen/main.cpp

https://github.com/emuharemagic/HPCC-Platform
C++ | 761 lines | 670 code | 73 blank | 18 comment | 140 complexity | 1822df1389d8abc606909350b4ddac4f MD5 | raw file
  1/*##############################################################################
  2
  3    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  4
  5    Licensed under the Apache License, Version 2.0 (the "License");
  6    you may not use this file except in compliance with the License.
  7    You may obtain a copy of the License at
  8
  9       http://www.apache.org/licenses/LICENSE-2.0
 10
 11    Unless required by applicable law or agreed to in writing, software
 12    distributed under the License is distributed on an "AS IS" BASIS,
 13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14    See the License for the specific language governing permissions and
 15    limitations under the License.
 16############################################################################## */
 17#include "jliball.hpp"
 18#include "XMLTags.h"
 19#include "configengcallback.hpp"
 20#include "deploy.hpp"
 21#include "build-config.h"
 22
 23#define STANDARD_INDIR COMPONENTFILES_DIR"/configxml"
 24#define STANDARD_OUTDIR RUNTIME_DIR
 25
 26void usage()
 27{
 28  const char* version = "1.1";
 29  printf("HPCC Systems configuration generator. version %s. Usage:\n", version);
 30  puts("   configgen -env <environment file> -ip <ip addr> [options]");
 31  puts("");
 32  puts("options: ");
 33  puts("   -env : The configuration environment to be parsed.");
 34  puts("   -ip  : The ip address that will be matched against a component ");
 35  puts("          instance's ip address. If matched, configuration files are ");
 36  puts("          generated for that component");
 37  puts("   -c <component name>: Optional component name for which the ");
 38  puts("          configuration is generated. If -t is also specified, it is ");
 39  puts("          ignored");
 40  puts("   -t <component type>: Optional component type for which the ");
 41  puts("          configuration is generated. If -c is also specified, the ");
 42  puts("          component name is used");
 43  puts("   -id <input directory>: The input directory for the supporting ");
 44  puts("          xml environment files like xsd's, xsl's and ");
 45  puts("          configgencomplist.xml. If not specified, the following ");
 46  puts("          defaults are used. ");
 47  puts("          For win32, 'c:\\trunk\\initfiles\\componentfiles\\configxml'");
 48  puts("          For Linux, '"COMPONENTFILES_DIR"/configxml/'");
 49  puts("   -od <output directory>: The output directory for the generated files.");
 50  puts("          If not specified, the following defaults are used. ");
 51  puts("          For win32, '.'");
 52  puts("          For Linux, '"CONFIG_DIR"'");
 53  puts("   -ldapconfig : Generates a .ldaprc file and puts it in the specified");
 54  puts("          output directory. If output directory is not specified,");
 55  puts("          default output directory is used as mentioned in -od option");
 56  puts("          if a LDAPServer is not defined in the environment, the .ldaprc ");
 57  puts("          file is not generated. If an -ip is not provided, the first");
 58  puts("          instance of the first LDAPserver is used to generate the ");
 59  puts("          .ldaprc file");
 60  puts("   -list: Lists out the components for a specific ip in the format");
 61  puts("          componentType=componentName;config file directory. Does not ");
 62  puts("          generate any output files. If masters and slaves exist for ");
 63  puts("          a component like Roxie or thor, then only the master entry ");
 64  puts("          is returned. ");
 65  puts("   -listall: Lists out all the components specified in the environment");
 66  puts("          that have an instance defined. Does not require an ip. Does ");
 67  puts("          not generate any output files. Output is written to stdout ");
 68  puts("          in the csv format as follows");
 69  puts("          ProcessType,componentName,instanceip,instanceport,runtimedir,logdir");
 70  puts("          Missing fields will be empty.");
 71  puts("   -listdirs: Lists out any directories that need to be created during ");
 72  puts("          init time. Currently, directories for any drop zones ");
 73  puts("          with the same ip as the -ip option are returned. Format is ");
 74  puts("          one directory per line.");
 75  puts("   -listdropzones: Lists out all the dropzones defined in the environment ");
 76  puts("          Does not require an ip. Does not generate any output files.");
 77  puts("          Output is written to stdout. Format is as follows,");
 78  puts("          one entry per line");
 79  puts("          dropzone node ip,dropzone directory");
 80  puts("   -listcommondirs: Lists out all directories that are listed under ");
 81  puts("          Software/Directories section in the following format. ");
 82  puts("          <CategoryName>=<DirectoryValue>");
 83  puts("          Each directory will be listed on a new line.");
 84  puts("   -listldaps: Lists out all LDAPServer instances defined in the ");
 85  puts("          environment in the following format. If the same component");
 86  puts("          has more than one instance, it will be listed as two separate.");
 87  puts("          entries in the output");
 88  puts("          componentName,instanceip");
 89  puts("   -machines: Lists out all names or ips of machines specified in the environment");
 90  puts("          Output is written to stdout, one machine per line.");
 91  puts("   -validateonly: Validates the environment, without generating permanent ");
 92  puts("          configurations. Returns 0 if environment is valid and non zero ");
 93  puts("          in other cases. Validation errors are printed to stderr.");
 94  puts("          Ignores -od flag, if supplied.");
 95  puts("   -v   : Print verbose output to stdout");
 96  puts("   -help: print out this usage.");
 97}
 98
 99void deleteRecursive(const char* path)
100{
101    Owned<IFile> pDir = createIFile(path);
102    if (pDir->exists())
103    {
104        if (pDir->isDirectory())
105        {
106            Owned<IDirectoryIterator> it = pDir->directoryFiles(NULL, false, true);
107            ForEach(*it)
108            {               
109                StringBuffer name;
110                it->getName(name);
111                
112                StringBuffer childPath(path);
113                childPath.append(PATHSEPCHAR);
114                childPath.append(name);
115                
116                deleteRecursive(childPath.str());
117            }
118        }
119        pDir->remove();
120    }
121}
122
123void copyDirectoryRecursive(const char *source, const char *target)
124{
125  bool first = true;
126  Owned<IDirectoryIterator> dir = createDirectoryIterator(source, "*");
127
128  ForEach (*dir)
129  {
130    IFile &sourceFile = dir->query();
131
132    if (sourceFile.isFile())
133    {
134      StringBuffer targetname(target);
135      targetname.append(PATHSEPCHAR);
136      dir->getName(targetname);
137      OwnedIFile destFile = createIFile(targetname.str());
138
139      if (first)
140      {
141        if (!recursiveCreateDirectory(target))
142          throw MakeStringException(-1,"Cannot create directory %s",target);
143
144        first = false;
145      }
146
147      copyFile(destFile, &sourceFile);
148    }
149    else if (sourceFile.isDirectory())
150    {
151      StringBuffer newSource(source);
152      StringBuffer newTarget(target);
153      newSource.append(PATHSEPCHAR);
154      newTarget.append(PATHSEPCHAR);
155      dir->getName(newSource);
156      dir->getName(newTarget);
157      copyDirectoryRecursive(newSource.str(), newTarget.str());
158    }
159  }
160}
161
162//returns temp path that ends with path sep
163//
164#ifdef _WIN32
165extern DWORD getLastError() { return ::GetLastError(); }
166void getTempPath(char* tempPath, unsigned int bufsize, const char* subdir/*=NULL*/)
167{
168  ::GetTempPath(bufsize, tempPath);
169  ::GetLongPathName(tempPath, tempPath, bufsize);
170  if (subdir && *subdir)
171  {
172    const int len = strlen(tempPath);
173    char* p = tempPath + len;
174    strcpy(p, subdir);
175    p += strlen(subdir);
176    *p++ = '\\';
177    *p = '\0';
178  }
179}
180#else//Linux specifics follow
181extern DWORD getLastError() { return errno; }
182void getTempPath(char* tempPath, unsigned int bufsize, const char* subdir/*=NULL*/)
183{
184  assert(bufsize > 5);
185  strcpy(tempPath, "/tmp/");
186  if (subdir && *subdir)
187  {
188    strcat(tempPath, subdir);
189    strcat(tempPath, "/");
190  }
191}
192#endif
193
194void replaceDotWithHostIp(IPropertyTree* pTree, bool verbose)
195{
196    StringBuffer ip;
197    queryHostIP().getIpText(ip);
198    const char* attrs[] = {"@netAddress", "@roxieAddress", "@daliAddress"};
199    StringBuffer xPath;
200
201    for (int i = 0; i < sizeof(attrs)/sizeof(char*); i++)
202    {
203        xPath.clear().appendf(".//*[%s]", attrs[i]);
204        Owned<IPropertyTreeIterator> iter = pTree->getElements(xPath.str());
205
206        ForEach(*iter)
207        {
208            IPropertyTree* pComponent = &iter->query();
209            Owned<IAttributeIterator> iAttr = pComponent->getAttributes();
210
211            ForEach(*iAttr)
212            {
213                const char* attrName = iAttr->queryName();
214
215                if (!strcmp(attrName, attrs[i]))
216                {
217                    String sAttrVal(iAttr->queryValue());
218                    String dot(".");
219                    
220                    if (sAttrVal.equals(dot) || sAttrVal.indexOf(".:") == 0 || sAttrVal.indexOf("http://.:") == 0)
221                    {
222                        StringBuffer sb(sAttrVal);
223                        if (sAttrVal.equals(dot))
224                            sb.replaceString(".", ip.str());
225                        else
226                        {
227                            ip.append(":");
228                            sb.replaceString(".:", ip.str());
229                            ip.remove(ip.length() - 1, 1);
230                        }
231                        
232                        pComponent->setProp(attrName, sb.str());
233
234                        if (verbose)
235                            fprintf(stdout, "Replacing '.' with host ip '%s' for component/attribute '%s'[@'%s']\n", ip.str(), pComponent->queryName(), attrName);
236                    }
237                }
238            }    
239        }
240    }
241}
242
243int processRequest(const char* in_cfgname, const char* out_dirname, const char* in_dirname, 
244                   const char* compName, const char* compType, const char* in_filename, 
245                   const char* out_filename, bool generateOutput, const char* ipAddr, 
246                   bool listComps, bool verbose, bool listallComps, bool listdirs, 
247                   bool listdropzones, bool listcommondirs, bool listMachines, bool validateOnly,
248                   bool listldaps, bool ldapconfig)
249{
250  Owned<IPropertyTree> pEnv = createPTreeFromXMLFile(in_cfgname);
251  short nodeIndex = 1;
252  short index = 1;
253  short compTypeIndex = 0;
254  short buildSetIndex = 0;
255  StringBuffer lastCompAdded;
256  StringBuffer xPath("*");
257  CConfigEngCallback callback(verbose);
258  Owned<IPropertyTreeIterator> iter = pEnv->getElements(xPath.str());
259  Owned<IConstEnvironment> m_pConstEnvironment;
260  Owned<IEnvironment>      m_pEnvironment;
261
262  replaceDotWithHostIp(pEnv, verbose); 
263  StringBuffer envXML;
264  toXML(pEnv, envXML);
265
266  Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
267  m_pEnvironment.setown(factory->loadLocalEnvironment(envXML));
268  m_pConstEnvironment.set(m_pEnvironment);
269
270  if (validateOnly)
271  {
272    char tempdir[_MAX_PATH];
273    StringBuffer sb;
274
275    while(true)
276    {
277      sb.clear().appendf("%d", msTick());
278      getTempPath(tempdir, sizeof(tempdir), sb.str());
279
280      if (!checkDirExists(tempdir))
281      {
282        if (recursiveCreateDirectory(tempdir))
283          break;
284      }
285    }
286
287    try
288    {
289      Owned<IEnvDeploymentEngine> m_configGenMgr;
290      CConfigEngCallback callback(verbose, true);
291      m_configGenMgr.setown(createConfigGenMgr(*m_pConstEnvironment, callback, NULL, in_dirname?in_dirname:"", tempdir, NULL, NULL, NULL));
292      m_configGenMgr->deploy(DEFLAGS_CONFIGFILES, DEBACKUP_NONE, false, false);
293      deleteRecursive(tempdir);
294    }
295    catch(IException* e)
296    {
297      deleteRecursive(tempdir);
298      throw e;
299    }
300  }
301  else if (ldapconfig)
302  {
303    char tempdir[_MAX_PATH];
304    StringBuffer sb;
305
306    while(true)
307    {
308      sb.clear().appendf("%d", msTick());
309      getTempPath(tempdir, sizeof(tempdir), sb.str());
310
311      if (!checkDirExists(tempdir))
312      {
313        if (recursiveCreateDirectory(tempdir))
314          break;
315      }
316    }
317
318    StringBuffer out;
319    xPath.clear().append(XML_TAG_SOFTWARE"/"XML_TAG_LDAPSERVERPROCESS);
320    Owned<IPropertyTreeIterator> ldaps = pEnv->getElements(xPath.str());
321    Owned<IPropertyTree> pSelComps(createPTree("SelectedComponents"));
322    bool flag = false;
323
324    ForEach(*ldaps)
325    {
326      IPropertyTree* ldap = &ldaps->query();
327      IPropertyTree* inst;
328      int count = 1;
329      xPath.clear().appendf(XML_TAG_INSTANCE"[%d]", count);
330
331      while ((inst = ldap->queryPropTree(xPath.str())) != NULL)
332      {
333        if (ipAddr && *ipAddr && strcmp(ipAddr, inst->queryProp(XML_ATTR_NETADDRESS)))
334        {
335          ldap->removeTree(inst);
336          continue;
337        }
338
339        if (!flag)
340        {
341          inst->addProp(XML_ATTR_DIRECTORY, ".");
342          sb.clear().append(tempdir).append(PATHSEPCHAR).append(ldap->queryProp(XML_ATTR_NAME));
343          xPath.clear().appendf(XML_TAG_INSTANCE"[%d]", ++count);
344          flag = true;
345        }
346        else
347        {
348          ldap->removeTree(inst);
349        }
350      }
351
352      if (flag)
353      {
354        pSelComps->addPropTree(XML_TAG_LDAPSERVERPROCESS, createPTreeFromIPT(ldap));
355        break;
356      }
357    }
358
359    if (flag)
360    {
361      try
362      {
363        toXML(pEnv, envXML.clear());
364        m_pEnvironment.setown(factory->loadLocalEnvironment(envXML));
365        m_pConstEnvironment.set(m_pEnvironment);
366        Owned<IEnvDeploymentEngine> m_configGenMgr;
367        m_configGenMgr.setown(createConfigGenMgr(*m_pConstEnvironment, callback, pSelComps, in_dirname?in_dirname:"", tempdir, compName, compType, ipAddr));
368        m_configGenMgr->deploy(DEFLAGS_CONFIGFILES, DEBACKUP_NONE, false, false);
369        copyDirectoryRecursive(sb.str(), out_dirname);
370        deleteRecursive(tempdir);
371      }
372      catch (IException* e)
373      {
374        deleteRecursive(tempdir);
375        throw e;
376      }
377    }
378  }
379  else if (!listComps && !listallComps && !listdirs && !listdropzones && !listcommondirs && !listMachines
380           && !listldaps)
381  {
382    Owned<IEnvDeploymentEngine> m_configGenMgr;
383    m_configGenMgr.setown(createConfigGenMgr(*m_pConstEnvironment, callback, NULL, in_dirname?in_dirname:"", out_dirname?out_dirname:"", compName, compType, ipAddr));
384    m_configGenMgr->deploy(DEFLAGS_CONFIGFILES, DEBACKUP_NONE, false, false);
385  }
386  else if (listldaps)
387  {
388    StringBuffer out;
389    xPath.appendf("Software/%s/", XML_TAG_LDAPSERVERPROCESS);
390    Owned<IPropertyTreeIterator> ldaps = pEnv->getElements(xPath.str());
391
392    ForEach(*ldaps)
393    {
394      IPropertyTree* ldap = &ldaps->query();
395      Owned<IPropertyTreeIterator> insts = ldap->getElements(XML_TAG_INSTANCE);
396
397      ForEach(*insts)
398      {
399        IPropertyTree* inst = &insts->query();
400        StringBuffer computerName(inst->queryProp(XML_ATTR_COMPUTER));
401        xPath.clear().appendf("Hardware/Computer[@name=\"%s\"]", computerName.str());
402        IPropertyTree* pComputer = pEnv->queryPropTree(xPath.str());
403
404        if (pComputer)
405        {
406          const char* netAddr = pComputer->queryProp("@netAddress");
407          out.appendf("%s,%s\n", ldap->queryProp(XML_ATTR_NAME), netAddr);
408        }
409      }
410    }
411
412    fprintf(stdout, "%s", out.str());
413  }
414  else if (listdirs || listdropzones)
415  {
416    StringBuffer out;
417    xPath.clear().appendf("Software/%s", XML_TAG_DROPZONE);
418    Owned<IPropertyTreeIterator> dropZonesInsts = pEnv->getElements(xPath.str());
419    ForEach(*dropZonesInsts)
420    {
421      IPropertyTree* pDropZone = &dropZonesInsts->query();
422      StringBuffer computerName(pDropZone->queryProp(XML_ATTR_COMPUTER));
423      xPath.clear().appendf("Hardware/Computer[@name=\"%s\"]", computerName.str());
424      IPropertyTree* pComputer = pEnv->queryPropTree(xPath.str());
425      if (pComputer)
426      {
427        const char* netAddr = pComputer->queryProp("@netAddress");
428
429        if (listdropzones)
430          out.appendf("%s,%s\n", netAddr, pDropZone->queryProp(XML_ATTR_DIRECTORY));
431        else if (matchDeployAddress(ipAddr, netAddr))
432          out.appendf("%s\n", pDropZone->queryProp(XML_ATTR_DIRECTORY)); 
433      }
434    }
435
436    fprintf(stdout, "%s", out.str());
437  }
438  else if (listcommondirs)
439  {
440    StringBuffer out;
441    StringBuffer name;
442    xPath.clear().appendf("Software/Directories/@name");
443    name.append(pEnv->queryProp(xPath.str()));
444
445    xPath.clear().appendf("Software/Directories/Category");
446    Owned<IPropertyTreeIterator> dirInsts = pEnv->getElements(xPath.str());
447    ForEach(*dirInsts)
448    {
449      IPropertyTree* pDir = &dirInsts->query();
450      StringBuffer dirName(pDir->queryProp("@dir"));
451      int len = strrchr(dirName.str(), '/') - dirName.str();
452      dirName.setLength(len);
453
454      if (strstr(dirName.str(), "/[INST]") || strstr(dirName.str(), "/[COMPONENT]"))
455        continue;
456
457      dirName.replaceString("[NAME]", name.str());
458      out.appendf("%s=%s\n", pDir->queryProp(XML_ATTR_NAME), dirName.str()); 
459    }
460
461    fprintf(stdout, "%s", out.str());
462  }
463  else if (listMachines)
464  {
465    StringBuffer out;
466    Owned<IPropertyTreeIterator> computers = pEnv->getElements("Hardware/Computer");
467    ForEach(*computers)
468    {
469      IPropertyTree* pComputer = &computers->query();
470      const char *netAddress = pComputer->queryProp("@netAddress");
471      StringBuffer xpath;
472      const char* name = pComputer->queryProp(XML_ATTR_NAME);
473      bool isHPCCNode = false, isSqlOrLdap = false;
474
475      xpath.clear().appendf(XML_TAG_SOFTWARE"/*[//"XML_ATTR_COMPUTER"='%s']", name);
476      Owned<IPropertyTreeIterator> it = pEnv->getElements(xpath.str());
477
478      ForEach(*it)
479      {
480        IPropertyTree* pComponent = &it->query();
481
482        if (!strcmp(pComponent->queryName(), "MySQLProcess") ||
483            !strcmp(pComponent->queryName(), "LDAPServerProcess"))
484          isSqlOrLdap = true;
485        else
486        {
487          isHPCCNode = true;
488          break;
489        }
490      }
491
492      if (!isHPCCNode && isSqlOrLdap)
493        continue;
494
495      out.appendf("%s,", netAddress  ? netAddress : "");
496      const char *computerType = pComputer->queryProp("@computerType");
497
498      if (computerType)
499      {
500        xpath.clear().appendf("Hardware/ComputerType[@name='%s']", computerType);
501        IPropertyTree *pType = pEnv->queryPropTree(xpath.str());
502        out.appendf("%s", pType->queryProp("@opSys"));
503      }
504      out.newline();
505    }
506
507    fprintf(stdout, "%s", out.str());
508  }
509  else
510  {
511    StringBuffer out;
512    Owned<IPropertyTree> pSelectedComponents = getInstances(&m_pConstEnvironment->getPTree(), compName, compType, ipAddr, true);
513    Owned<IPropertyTreeIterator> it = pSelectedComponents->getElements("*");
514
515    ForEach(*it)
516    {
517      IPropertyTree* pComponent = &it->query();
518
519      if (listComps)
520      {
521        if (!strcmp(pComponent->queryProp("@buildSet"), "roxie") || !strcmp(pComponent->queryProp("@buildSet"), "thor"))
522        {
523          Owned<IPropertyTreeIterator> itInst = pComponent->getElements("*");
524          ForEach(*itInst)
525          {
526            IPropertyTree* pInst = &itInst->query();
527            String instName(pInst->queryName());
528            if (!strcmp(instName.toCharArray(), "ThorMasterProcess") || instName.startsWith("RoxieServerProcess"))
529            {
530              out.appendf("%s=%s;%s%c%s;%s\n", pComponent->queryProp("@name"), pComponent->queryProp("@buildSet"), out_dirname, PATHSEPCHAR, pComponent->queryProp("@name"),"master");
531            }
532          }
533        }
534        else
535          out.appendf("%s=%s;%s%c%s\n", pComponent->queryProp("@name"), pComponent->queryProp("@buildSet"), out_dirname, PATHSEPCHAR, pComponent->queryProp("@name"));
536      }
537      else if (listallComps)
538      {
539        StringBuffer netAddr;
540        StringBuffer port;
541        StringBuffer processName(pComponent->queryName());
542        bool multiInstances = false;
543
544        if(!strcmp(processName.str(), "ThorCluster") || !strcmp(processName.str(), "RoxieCluster"))
545        {
546          processName.clear();
547          multiInstances = true;
548        }
549
550        if (pComponent->numChildren())
551        {
552          Owned<IPropertyTreeIterator> itComp = pComponent->getElements("*");
553        
554          ForEach(*itComp)
555          {
556            IPropertyTree* pInst = &itComp->query();
557
558            if (!strcmp(pInst->queryName(), "ThorSlaveProcess") || !strcmp(pInst->queryName(), "ThorSpareProcess"))
559              continue;
560
561            netAddr.clear().append(pInst->queryProp("@netAddress"));
562            port.clear().append(pInst->queryProp("@port"));
563            
564            if (multiInstances)
565              processName.clear().append(pInst->queryName());
566
567            out.appendf("%s,%s,%s,%s,%s%c%s,%s\n", processName.str(), 
568              pComponent->queryProp("@name"), netAddr.str(), port.str(), 
569              STANDARD_OUTDIR, PATHSEPCHAR, pComponent->queryProp("@name"), pComponent->queryProp("@logDir"));
570          }
571        }
572        else 
573        {
574          netAddr.clear().append(pComponent->queryProp("@netAddress"));
575          port.clear().append(pComponent->queryProp("@port"));
576          out.appendf("%s,%s,%s,%s,%s%c%s,%s\n", pComponent->queryName(), 
577            pComponent->queryProp("@name"), netAddr.str(), port.str(), 
578              STANDARD_OUTDIR, PATHSEPCHAR, pComponent->queryProp("@name"), pComponent->queryProp("@logDir"));
579        }
580      }
581    }
582
583    fprintf(stdout, "%s", out.str());
584  }
585
586  return 0;
587}
588
589int main(int argc, char** argv)
590{
591  InitModuleObjects();
592
593  Owned<IProperties> globals = createProperties(true);
594  const char* in_filename = NULL;
595  const char* in_cfgname = NULL;
596  const char* out_dirname = STANDARD_OUTDIR;
597  const char* in_dirname = STANDARD_INDIR;
598  const char* out_filename = NULL;
599  const char* compName = NULL;
600  const char* compType = NULL;
601  StringBuffer ipAddr = NULL;
602  bool generateOutput = true;
603  bool listComps = false;
604  bool verbose = false;
605  bool listallComps = false;
606  bool listdirs = false;
607  bool listdropzones = false;
608  bool listcommondirs = false;
609  bool listMachines = false;
610  bool validateOnly = false;
611  bool ldapconfig = false;
612  bool listldaps = false;
613
614  int i = 1;
615  bool writeToFiles = false;
616  int port = 80;
617
618  while(i<argc)
619  {
620    if(stricmp(argv[i], "-help") == 0 || stricmp(argv[i], "-?") == 0)
621    {
622      usage();
623      releaseAtoms();
624      return 0;
625    }
626    else if (stricmp(argv[i], "-env") == 0)
627    {
628      i++;
629      in_cfgname = argv[i++];
630    }
631    else if (stricmp(argv[i], "-c") == 0)
632    {
633      i++;
634      compName = argv[i++];
635    }
636    else if (stricmp(argv[i], "-t") == 0)
637    {
638      i++;
639      compType = argv[i++];
640    }
641    else if (stricmp(argv[i], "-ip") == 0)
642    {
643      i++;
644      ipAddr.append(argv[i++]);
645      if (strcmp(ipAddr, ".")!=0)
646      {
647        IpAddress ip(ipAddr.str());
648        ipAddr.clear();
649        if (ip.isLoopBack())                // assume they meant any local ip... not sure this is a good idea
650          ipAddr.append('.');
651        else
652          ip.getIpText(ipAddr);
653      }
654    }
655    else if(stricmp(argv[i], "-od") == 0)
656    {
657      i++;
658      out_dirname = argv[i++];
659    }
660    else if(stricmp(argv[i], "-id") == 0)
661    {
662      i++;
663      in_dirname = argv[i++];
664    }
665    else if (stricmp(argv[i], "-ldapconfig") == 0)
666    {
667      i++;
668      ldapconfig = true;
669    }
670    else if (stricmp(argv[i], "-list") == 0)
671    {
672      i++;
673      listComps = true;
674    }
675    else if (stricmp(argv[i], "-listall") == 0)
676    {
677      i++;
678      listallComps = true;
679    }
680    else if (stricmp(argv[i], "-listdirs") == 0)
681    {
682      i++;
683      listdirs = true;
684    }
685    else if (stricmp(argv[i], "-listdropzones") == 0)
686    {
687      i++;
688      listdropzones = true;
689    }
690    else if (stricmp(argv[i], "-listcommondirs") == 0)
691    {
692      i++;
693      listcommondirs = true;
694    }
695    else if (stricmp(argv[i], "-listldaps") == 0)
696    {
697      i++;
698      listldaps = true;
699    }
700    else if (stricmp(argv[i], "-machines") == 0)
701    {
702      i++;
703      listMachines = true;
704    }
705    else if (stricmp(argv[i], "-validateonly") == 0)
706    {
707      i++;
708      validateOnly = true;
709    }
710    else if (stricmp(argv[i], "-v") == 0)
711    {
712      i++;
713      verbose = true;
714    }
715    else
716    {
717      fprintf(stderr, "Error: unknown command line parameter: %s\n", argv[i]);
718      usage();
719      releaseAtoms();
720      return 1;
721    }
722  }
723
724  if (!in_cfgname)
725  {
726    fprintf(stderr, "Error: Environment xml file is required. Please specify.\n");
727    usage();
728    releaseAtoms();
729    return 1;
730  }
731
732  if (ipAddr.length() == 0  && !listallComps && !validateOnly && !listcommondirs && !listMachines && !listldaps && !ldapconfig)
733    ipAddr.clear().append("."); // Meaning match any local address
734
735  try
736  {
737    processRequest(in_cfgname, out_dirname, in_dirname, compName, 
738      compType,in_filename, out_filename, generateOutput, ipAddr.length() ? ipAddr.str(): NULL,
739      listComps, verbose, listallComps, listdirs, listdropzones, listcommondirs, listMachines,
740      validateOnly, listldaps, ldapconfig);
741  }
742  catch(IException *excpt)
743  {
744    StringBuffer errMsg;
745    fprintf(stderr, "Exception: %d:\n%s\n", excpt->errorCode(), excpt->errorMessage(errMsg).str());
746    releaseAtoms();
747    excpt->Release();
748    return 1;
749  }
750  catch(...)
751  {
752    fprintf(stderr, "Unknown exception\n");
753    releaseAtoms();
754    return 1;
755  }
756
757  releaseAtoms();
758
759  return 0;
760}
761