1 /*==============================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 
27 #include "configure.h"
28 
29 #include <cloud/manager.h> /* CloudMgrRelease */
30 
31 #include <kapp/main.h>
32 #include <kapp/args-conv.h>
33 
34 #include <vdb/vdb-priv.h> /* VDBManagerListExternalSchemaModules */
35 #include <vdb/manager.h> /* VDBManager */
36 
37 #include <kfg/kfg-priv.h> /* KConfig */
38 #include <kfg/ngc.h> /* KNgcObjMakeFromFile */
39 #include <kfg/properties.h> /* KConfig_Get_Default_User_Path */
40 #include <kfg/repository.h> /* KConfigImportNgc */
41 
42 #include <vfs/manager.h> /* VFSManagerMake */
43 #include <vfs/path-priv.h> /* KPathGetCWD */
44 
45 #include <kfs/directory.h>
46 #include <kfs/file.h>
47 #include <kfs/impl.h> /* KDirectoryGetSysDir */
48 #include <kfs/kfs-priv.h> /* KSysDirOSPath */
49 
50 #include <klib/log.h> /* LOGERR */
51 #include <klib/misc.h> /* is_iser_an_admin */
52 #include <klib/namelist.h>
53 #include <klib/out.h> /* OUTMSG */
54 #include <klib/printf.h> /* string_printf */
55 #include <klib/rc.h> /* RC */
56 #include <klib/text.h> /* strcase_cmp */
57 
58 #include <sysalloc.h> /* redefine malloc etc calls */
59 #include <os-native.h> /* SHLX */
60 
61 #include <assert.h>
62 #include <ctype.h> /* tolower */
63 #include <errno.h>
64 #include <stdio.h> /* scanf */
65 #include <stdlib.h> /* getenv */
66 #include <string.h> /* memset */
67 
68 #include <limits.h> /* PATH_MAX */
69 
70 #ifndef PATH_MAX
71 #define PATH_MAX 4096
72 #endif
73 
74 #define DISP_RC(rc, msg) (void)((rc == 0) ? 0 : LOGERR(klogInt, rc, msg))
75 #define DISP_RC2(rc, name, msg) (void)((rc == 0) ? 0 : \
76     PLOGERR(klogInt, (klogInt, rc, \
77         "$(name): $(msg)", "name=%s,msg=%s", name, msg)))
78 #define RELEASE(type, obj) do { rc_t rc2 = type##Release(obj); \
79     if (rc2 && !rc) { rc = rc2; } obj = NULL; } while (false)
80 
81 #define ALIAS_ALL    "a"
82 #define OPTION_ALL   "all"
83 static const char* USAGE_ALL[] = { "print all information [default]", NULL };
84 
85 #define ALIAS_CFG    "i"
86 #define OPTION_CFG   "interactive"
87 static const char* USAGE_CFG[] = {
88     "create/update configuration",
89     NULL };
90 
91 #define ALIAS_CFM    NULL
92 #define OPTION_CFM   "interactive-mode"
93 static const char* USAGE_CFM[] = {
94     "interactive mode: 'textual' or 'graphical' (default)",
95     NULL };
96 
97 #define ALIAS_DIR    "d"
98 #define OPTION_DIR   "load-path"
99 static const char* USAGE_DIR[] = { "print load path", NULL };
100 
101 #define ALIAS_ENV    "e"
102 #define OPTION_ENV   "env"
103 static const char* USAGE_ENV[] = { "print shell variables", NULL };
104 
105 #define ALIAS_FIL    "f"
106 #define OPTION_FIL   "files"
107 static const char* USAGE_FIL[] = { "print loaded files", NULL };
108 
109 #define ALIAS_FIX    NULL
110 #define OPTION_FIX   "restore-defaults"
111 static const char* USAGE_FIX[] =
112 { "create default or update existing user configuration", NULL };
113 
114 #define ALIAS_MOD    "m"
115 #define OPTION_MOD   "modules"
116 static const char* USAGE_MOD[] = { "print external modules", NULL };
117 
118 #define ALIAS_OUT    "o"
119 #define OPTION_OUT   "output"
120 static const char* USAGE_OUT[] = { "output type: one of (x n), "
121     "where 'x' is xml (default), 'n' is native", NULL };
122 
123 #define ALIAS_PCF    "p"
124 #define OPTION_PCF   "cfg"
125 static const char* USAGE_PCF[] = { "print current configuration", NULL };
126 
127 #define ALIAS_PRTCT  NULL
128 #define OPTION_PRTCT "ignore-protected-repositories"
129 static const char* USAGE_PRTCT[] =
130 { "stop printing warning message when protected repository is found", NULL };
131 
132 #define ALIAS_CDR    NULL
133 #define OPTION_CDR   "cfg-dir"
134 static const char* USAGE_CDR[]
135     = { "set directory to load configuration", NULL };
136 
137 #define ALIAS_PRD    NULL
138 #define OPTION_PRD   "proxy-disable"
139 static const char* USAGE_PRD[] = { "enable/disable using HTTP proxy", NULL };
140 
141 #define ALIAS_PRX    NULL
142 #define OPTION_PRX   "proxy"
143 static const char* USAGE_PRX[]
144     = { "set HTTP proxy server configuration", NULL };
145 
146 #define ALIAS_ROOT   NULL
147 #define OPTION_ROOT  "root"
148 static const char* USAGE_ROOT[] =
149     { "enforce configuration update while being run by superuser", NULL };
150 
151 #define ALIAS_SET    "s"
152 #define OPTION_SET   "set"
153 static const char* USAGE_SET[] = { "set configuration node value", NULL };
154 
155 #define ALIAS_C_IN  "C"
156 #define OPTION_C_IN "cloud-info"
157 static const char* USAGE_C_IN[]
158     = { "display cloud-releated information", NULL };
159 
160 #define ALIAS_C_RI  NULL
161 #define OPTION_C_RI "report-cloud-identity"
162 static const char* USAGE_C_RI[]
163     = { "give permission to report cloud instance identity", NULL };
164 
165 #define ALIAS_S3_C  NULL
166 #define OPTION_S3_C "accept-aws-charges"
167 static const char* USAGE_S3_C[]
168     = { "agree to accept charges for AWS usage", NULL };
169 
170 #define ALIAS_S3_F  NULL
171 #define OPTION_S3_F "set-aws-credentials"
172 static const char* USAGE_S3_F[] = { "select file with AWS credentials", NULL };
173 
174 #define ALIAS_S3_P  NULL
175 #define OPTION_S3_P "set-aws-profile"
176 static const char* USAGE_S3_P[] = { "set AWS profile", NULL };
177 
178 #define ALIAS_GS_C  NULL
179 #define OPTION_GS_C "accept-gcp-charges"
180 static const char* USAGE_GS_C[]
181 = { "agree to accept charges for GCP usage", NULL };
182 
183 #define ALIAS_GS_F  NULL
184 #define OPTION_GS_F "set-gcp-credentials"
185 static const char* USAGE_GS_F[] = { "select file with GCP credentials", NULL };
186 
187 #define ALIAS_P_CW  NULL
188 #define OPTION_P_CW "prefetch-to-cwd"
189 static const char* USAGE_P_CW[] = { "prefetch downloads to "
190     "current directory when public user repository is set (default: false)",
191     NULL };
192 
193 #define ALIAS_P_UR NULL
194 #define OPTION_P_UR "prefetch-to-user-repo"
195 static const char* USAGE_P_UR[] = { "prefetch downloads to "
196     "public user repository when it is set (default)", NULL };
197 
WorkspaceDirPathConv(const Args * args,uint32_t arg_index,const char * arg,size_t arg_len,void ** result,WhackParamFnP * whack)198 rc_t WorkspaceDirPathConv(const Args * args, uint32_t arg_index, const char * arg, size_t arg_len, void ** result, WhackParamFnP * whack)
199 {
200     uint32_t imp_count = 0;
201 
202 /*  rc_t rc = ArgsOptionCount(args, OPTION_IMP, &imp_count);
203     if (rc != 0)
204         return rc; */
205 
206     // first parameter is a directory only if OPTION_IMP is present; otherwise it is a query
207     if (imp_count > 0)
208     {
209         return ArgsConvFilepath(args, arg_index, arg, arg_len, result, whack);
210     }
211 
212     return ArgsConvDefault(args, arg_index, arg, arg_len, result, whack);
213 }
214 
215 OptDef Options[] =
216 {                                         /* needs_value, required, converter */
217       { OPTION_ALL, ALIAS_ALL, NULL, USAGE_ALL, 1, false, false, NULL }
218     , { OPTION_CDR, ALIAS_CDR, NULL, USAGE_CDR, 1, true , false, NULL }
219     , { OPTION_CFG, ALIAS_CFG, NULL, USAGE_CFG, 1, false, false, NULL }
220     , { OPTION_CFM, ALIAS_CFM, NULL, USAGE_CFM, 1, true , false, NULL }
221     , { OPTION_DIR, ALIAS_DIR, NULL, USAGE_DIR, 1, false, false, NULL }
222     , { OPTION_ENV, ALIAS_ENV, NULL, USAGE_ENV, 1, false, false, NULL }
223     , { OPTION_FIL, ALIAS_FIL, NULL, USAGE_FIL, 1, false, false, NULL }
224     , { OPTION_FIX, ALIAS_FIX, NULL, USAGE_FIX, 1, false, false, NULL }
225     , {OPTION_PRTCT,ALIAS_PRTCT,NULL,USAGE_PRTCT,1,false, false, NULL }
226     , { OPTION_MOD, ALIAS_MOD, NULL, USAGE_MOD, 1, false, false, NULL }
227     , { OPTION_OUT, ALIAS_OUT, NULL, USAGE_OUT, 1, true , false, NULL }
228     , { OPTION_C_IN,ALIAS_C_IN,NULL, USAGE_C_IN,1, false, false, NULL }
229     , { OPTION_C_RI,ALIAS_C_RI,NULL, USAGE_C_RI,1, true , false, NULL }
230     , { OPTION_S3_C,ALIAS_S3_C,NULL, USAGE_S3_C,1, true , false, NULL }
231     , { OPTION_S3_F,ALIAS_S3_F,NULL, USAGE_S3_F,1, true , false, NULL }
232     , { OPTION_S3_P,ALIAS_S3_P,NULL, USAGE_S3_P,1, true , false, NULL }
233     , { OPTION_GS_F,ALIAS_GS_F,NULL, USAGE_GS_F,1, true , false, NULL }
234     , { OPTION_GS_C,ALIAS_GS_C,NULL, USAGE_GS_C,1, true , false, NULL }
235     , { OPTION_P_CW,ALIAS_P_CW,NULL, USAGE_P_CW,1, false, false, NULL }
236     , { OPTION_P_UR,ALIAS_P_UR,NULL, USAGE_P_UR,1, false, false, NULL }
237     , { OPTION_PCF, ALIAS_PCF, NULL, USAGE_PCF, 1, false, false, NULL }
238     , { OPTION_PRD, ALIAS_PRD, NULL, USAGE_PRD, 1, true , false, NULL }
239     , { OPTION_PRX, ALIAS_PRX, NULL, USAGE_PRX, 1, true , false, NULL }
240     , { OPTION_SET, ALIAS_SET, NULL, USAGE_SET, 1, true , false, NULL }
241     , { OPTION_ROOT,ALIAS_ROOT,NULL, USAGE_ROOT,1, false, false, NULL }
242 };
243 
244 ParamDef Parameters[] =
245 {
246     { WorkspaceDirPathConv }
247 };
248 
UsageSummary(const char * progname)249 rc_t CC UsageSummary (const char * progname) {
250     return KOutMsg (
251         "Usage:\n"
252         "  %s [options] [<query> ...]\n\n"
253         "Summary:\n"
254         "  Manage VDB configuration\n"
255         , progname, progname);
256 }
257 
Usage(const Args * args)258 rc_t CC Usage(const Args* args) {
259     rc_t rc = 0;
260 
261     const char* progname = UsageDefaultName;
262     const char* fullpath = UsageDefaultName;
263 
264     if (args == NULL) {
265         rc = RC(rcExe, rcArgv, rcAccessing, rcSelf, rcNull);
266     }
267     else {
268         rc = ArgsProgram(args, &fullpath, &progname);
269     }
270 
271     UsageSummary(progname);
272 
273     KOutMsg ("\nOptions:\n");
274 
275     HelpOptionLine (ALIAS_ALL, OPTION_ALL, NULL, USAGE_ALL);
276     HelpOptionLine (ALIAS_PCF, OPTION_PCF, NULL, USAGE_PCF);
277     HelpOptionLine (ALIAS_FIL, OPTION_FIL, NULL, USAGE_FIL);
278     HelpOptionLine (ALIAS_DIR, OPTION_DIR, NULL, USAGE_DIR);
279     HelpOptionLine (ALIAS_ENV, OPTION_ENV, NULL, USAGE_ENV);
280     HelpOptionLine (ALIAS_MOD, OPTION_MOD, NULL, USAGE_MOD);
281     KOutMsg ("\n");
282     HelpOptionLine (ALIAS_SET, OPTION_SET, "name=value", USAGE_SET);
283     KOutMsg ("\n");
284     HelpOptionLine (ALIAS_CFG, OPTION_CFG, NULL, USAGE_CFG);
285     HelpOptionLine (ALIAS_CFM, OPTION_CFM, "mode", USAGE_CFM);
286     KOutMsg ("\n");
287     HelpOptionLine (ALIAS_FIX, OPTION_FIX, NULL, USAGE_FIX);
288     HelpOptionLine(ALIAS_PRTCT,OPTION_PRTCT,NULL,USAGE_PRTCT);
289     KOutMsg ("\n");
290     HelpOptionLine (ALIAS_OUT, OPTION_OUT, "x | n", USAGE_OUT);
291     KOutMsg ("\n");
292     HelpOptionLine(ALIAS_C_IN, OPTION_C_IN, NULL, USAGE_C_IN);
293     HelpOptionLine(ALIAS_C_RI, OPTION_C_RI, "yes | no", USAGE_C_RI);
294     HelpOptionLine(ALIAS_S3_C, OPTION_S3_C, "yes | no", USAGE_S3_C);
295     HelpOptionLine(ALIAS_S3_F, OPTION_S3_F, "path", USAGE_S3_F);
296     HelpOptionLine(ALIAS_S3_P, OPTION_S3_P, "profile", USAGE_S3_P);
297     HelpOptionLine(ALIAS_GS_C, OPTION_GS_C, "yes | no", USAGE_GS_C);
298     HelpOptionLine(ALIAS_GS_F, OPTION_GS_F, "path", USAGE_GS_F);
299     KOutMsg ("\n");
300     HelpOptionLine(ALIAS_P_CW, OPTION_P_CW, NULL, USAGE_P_CW);
301     HelpOptionLine(ALIAS_P_UR, OPTION_P_UR, NULL, USAGE_P_UR);
302     KOutMsg("\n");
303     HelpOptionLine (ALIAS_PRX, OPTION_PRX, "uri[:port]", USAGE_PRX);
304     HelpOptionLine (ALIAS_PRD, OPTION_PRD, "yes | no", USAGE_PRD);
305     KOutMsg ("\n");
306     HelpOptionLine (ALIAS_CDR, OPTION_CDR, "path", USAGE_CDR);
307     KOutMsg ("\n");
308     HelpOptionLine (ALIAS_ROOT,OPTION_ROOT,NULL, USAGE_ROOT);
309 
310     KOutMsg ("\n");
311 
312     HelpOptionsStandard ();
313 
314     HelpVersion (fullpath, KAppVersion());
315 
316     return rc;
317 }
318 
319 const char UsageDefaultName[] = "vdb-config";
320 
Indent(bool xml,int n)321 static void Indent(bool xml, int n) {
322     if (!xml)
323     {   return; }
324     while (n--)
325     {   OUTMSG(("  ")); }
326 }
327 
KConfigNodeReadData(const KConfigNode * self,char * buf,size_t blen,size_t * num_read)328 static rc_t KConfigNodeReadData(const KConfigNode* self,
329     char* buf, size_t blen, size_t* num_read)
330 {
331     rc_t rc = 0;
332     size_t remaining = 0;
333     assert(buf && blen && num_read);
334     rc = KConfigNodeRead(self, 0, buf, blen, num_read, &remaining);
335     assert(remaining == 0); /* TODO overflow check */
336     assert(*num_read <= blen);
337     return rc;
338 }
339 
340 static
_printNodeData(const char * name,const char * data,size_t dlen)341 rc_t _printNodeData(const char *name, const char *data, size_t dlen)
342 {
343     bool secret = false;
344     {
345         const char d1[] = "download-ticket";
346         size_t l1 = sizeof d1 - 1;
347 
348         const char d2[] = "aws_access_key_id";
349         size_t l2 = sizeof d2 - 1;
350 
351         const char d3[] = "aws_secret_access_key";
352         size_t l3 = sizeof d3 - 1;
353 
354         if ((string_cmp(name,
355                 string_measure(name, NULL), d1, l1, (uint32_t)l1) == 0) ||
356             (string_cmp(name,
357                 string_measure(name, NULL), d2, l2, (uint32_t)l2) == 0) ||
358             (string_cmp(name,
359                 string_measure(name, NULL), d3, l3, (uint32_t)l3) == 0))
360         {
361             secret = true;
362         }
363     }
364 
365     if (secret) {
366         const char *ellipsis = "";
367         const char replace[] =
368 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
369         if (dlen > 70) {
370             dlen = 70;
371             ellipsis = "...";
372         }
373         return OUTMSG(("%.*s%s", (uint32_t)dlen, replace, ellipsis));
374     }
375     else {
376         return OUTMSG(("%.*s", dlen, data));
377     }
378 }
379 
380 #define VDB_CONGIG_OUTMSG(args) do { if (xml) { OUTMSG(args); } } while (false)
KConfigNodePrintChildNames(bool xml,const KConfigNode * self,const char * name,int indent,const char * aFullpath)381 static rc_t KConfigNodePrintChildNames(bool xml, const KConfigNode* self,
382     const char* name, int indent, const char* aFullpath)
383 {
384     rc_t rc = 0;
385     uint32_t count = 0;
386     int i = 0;
387     char buffer[8192] = "";
388     size_t num_read = 0;
389     bool hasChildren = false;
390     bool hasData = false;
391     const KConfigNode* node = NULL;
392     KNamelist* names = NULL;
393     bool beginsWithNumberinXml = false;
394     assert(self && name);
395 
396     if (rc == 0)
397     {   rc = KConfigNodeOpenNodeRead(self, &node, "%s", name);  }
398     if (rc == 0) {
399         rc = KConfigNodeReadData(node, buffer, sizeof buffer, &num_read);
400         hasData = num_read > 0;
401         if (hasData) {
402  /* VDB_CONGIG_OUTMSG(("\n%s = \"%.*s\"\n\n", aFullpath, num_read, buffer)); */
403         }
404     }
405     if (rc == 0) {
406         rc = KConfigNodeListChild(node, &names);
407     }
408     if (rc == 0) {
409         rc = KNamelistCount(names, &count);
410         hasChildren = count;
411     }
412 
413     Indent(xml, indent);
414     if (xml) {
415         beginsWithNumberinXml = isdigit(name[0]);
416         if (! beginsWithNumberinXml) {
417             VDB_CONGIG_OUTMSG(("<%s", name));
418         }
419         else {
420             /* XML node names cannot start with a number */
421             VDB_CONGIG_OUTMSG(("<_%s", name));
422         }
423     }
424     if (!hasChildren && !hasData) {
425         VDB_CONGIG_OUTMSG(("/>\n"));
426     }
427     else {   VDB_CONGIG_OUTMSG((">"));
428     }
429     if (hasData) {
430         if (xml) {
431             _printNodeData(name, buffer, num_read);
432         }
433         else {
434             OUTMSG(("%s = \"", aFullpath));
435             _printNodeData(name, buffer, num_read);
436             OUTMSG(("\"\n"));
437         }
438     }
439     if (hasChildren)
440     {   VDB_CONGIG_OUTMSG(("\n"));}
441 
442     if (hasChildren) {
443         for (i = 0; i < (int)count && rc == 0; ++i) {
444             char* fullpath = NULL;
445             const char* name = NULL;
446             rc = KNamelistGet(names, i, &name);
447             if (rc == 0) {
448                 size_t bsize = strlen(aFullpath) + 1 + strlen(name) + 1;
449                 fullpath = malloc(bsize + 1);
450                 if (fullpath == NULL) {
451                     rc = RC
452                         (rcExe, rcStorage, rcAllocating, rcMemory, rcExhausted);
453                 }
454                 else {
455                     string_printf(fullpath, bsize, NULL,
456                         "%s/%s", aFullpath, name);
457                 }
458             }
459             if (rc == 0) {
460                 rc = KConfigNodePrintChildNames
461                     (xml, node, name, indent + 1, fullpath);
462             }
463             free(fullpath);
464         }
465     }
466 
467     if (hasChildren)
468     {   Indent(xml, indent); }
469     if (hasChildren || hasData)
470     {
471         if (! beginsWithNumberinXml) {
472             VDB_CONGIG_OUTMSG(("</%s>\n",name));
473         }
474         else {
475             VDB_CONGIG_OUTMSG(("</_%s>\n",name));
476         }
477     }
478 
479     RELEASE(KNamelist, names);
480     RELEASE(KConfigNode, node);
481     return rc;
482 }
483 
484 typedef enum {
485     eNotSet,
486     eFalse,
487     eTrue
488 } EState;
489 
490 typedef struct Params {
491     Args* args;
492     uint32_t argsParamIdx;
493     uint32_t argsParamCnt;
494 
495     const char *cfg_dir;
496 
497     bool xml;
498 
499     const char *setValue;
500 
501     const char *ngc;
502 
503     bool modeSetNode;
504     bool modeConfigure;
505     bool ignoreProtected;
506     EConfigMode configureMode;
507     bool modeCreate;
508     bool modeShowCfg;
509     bool modeShowEnv;
510     bool modeShowFiles;
511     bool modeShowLoadPath;
512     bool modeShowModules;
513     bool modeRoot;
514 
515     bool showMultiple;
516 
517     enum {
518         eUndefined,
519         eNo,
520         eYes
521     } proxyDisabled;
522     const char *proxy;
523 
524     bool modeCloud; /* cloud-releated mode */
525     bool cloudInfo;
526     EState cloudReportIdentity;
527     EState s3AcceptCharges;
528     const char * s3Credentials;
529     const char * s3Profile;
530     EState gsAcceptCharges;
531     const char * gsCredentials;
532     EState prefetchToCwd;
533 } Params;
534 
ParamsConstruct(int argc,char * argv[],Params * prm)535 static rc_t ParamsConstruct(int argc, char* argv[], Params* prm) {
536     rc_t rc = 0;
537     Args* args = NULL;
538     int count = 0;
539     assert(argc && argv && prm);
540     memset(prm, 0, sizeof *prm);
541     args = prm->args;
542     do {
543         const char* dummy = NULL;
544         uint32_t pcount = 0;
545         rc = ArgsMakeAndHandle2(&args, argc, argv, Parameters, sizeof Parameters / sizeof Parameters[0], 1, Options, sizeof Options / sizeof Options[0]);
546         if (rc) {
547             LOGERR(klogErr, rc, "While calling ArgsMakeAndHandle2");
548             break;
549         }
550 
551         prm->args = args;
552         rc = ArgsParamCount(args, &prm->argsParamCnt);
553         if (rc) {
554             LOGERR(klogErr, rc, "Failure to get query parameter[s]");
555             break;
556         }
557         if (prm->argsParamCnt > 0) {
558             prm->modeShowCfg = true;
559             ++count;
560         }
561 
562         {   // OPTION_OUT
563             prm->xml = true;
564             rc = ArgsOptionCount(args, OPTION_OUT, &pcount);
565             if (rc) {
566                 LOGERR(klogErr, rc, "Failure to get '" OPTION_OUT "' argument");
567                 break;
568             }
569             if (pcount) {
570                 rc = ArgsOptionValue(args, OPTION_OUT, 0, (const void **)&dummy);
571                 if (rc) {
572                     LOGERR(klogErr, rc, "Failure to get '" OPTION_OUT "' argument");
573                     break;
574                 }
575                 if (!strcmp(dummy, "n")) {
576                     prm->xml = false;
577                 }
578                 else if (strcmp(dummy, "x")) {
579                     rc = RC(rcExe, rcArgv, rcParsing, rcParam, rcInvalid);
580                     LOGERR(klogErr, rc, "Bad " OPTION_OUT " value");
581                     break;
582                 }
583             }
584         }
585         {   // OPTION_ENV
586             rc = ArgsOptionCount(args, OPTION_ENV, &pcount);
587             if (rc) {
588                 LOGERR(klogErr, rc, "Failure to get '" OPTION_ENV "' argument");
589                 break;
590             }
591             if (pcount) {
592                 prm->modeShowEnv = true;
593                 ++count;
594             }
595         }
596         {   // OPTION_CDR
597             rc = ArgsOptionCount(args, OPTION_CDR, &pcount);
598             if (rc != 0) {
599                 LOGERR(klogErr, rc, "Failure to get '" OPTION_CDR "' argument");
600                 break;
601             }
602             if (pcount > 0) {
603                 rc = ArgsOptionValue
604                     (args, OPTION_CDR, 0, (const void **)&prm->cfg_dir);
605                 if (rc) {
606                     LOGERR(klogErr, rc,
607                         "Failure to get '" OPTION_CDR "' argument");
608                     break;
609                 }
610             }
611         }
612         {   // OPTION_FIL
613             rc = ArgsOptionCount(args, OPTION_FIL, &pcount);
614             if (rc) {
615                 LOGERR(klogErr, rc, "Failure to get '" OPTION_FIL "' argument");
616                 break;
617             }
618             if (pcount > 0) {
619                 prm->modeShowFiles = true;
620                 ++count;
621             }
622         }
623         /* OPTION_MOD */
624         {
625             rc = ArgsOptionCount(args, OPTION_MOD, &pcount);
626             if (rc) {
627                 LOGERR(klogErr, rc, "Failure to get '" OPTION_MOD "' argument");
628                 break;
629             }
630             if (pcount) {
631                 prm->modeShowModules = true;
632                 ++count;
633             }
634         }
635         /* OPTION_PCF */
636         {
637             rc = ArgsOptionCount(args, OPTION_PCF, &pcount);
638             if (rc) {
639                 LOGERR(klogErr, rc, "Failure to get '" OPTION_PCF "' argument");
640                 break;
641             }
642             if (pcount) {
643                 if (!prm->modeShowCfg) {
644                     prm->modeShowCfg = true;
645                     ++count;
646                 }
647             }
648         }
649         {   // OPTION_PRD
650             rc = ArgsOptionCount(args, OPTION_PRD, &pcount);
651             if (rc != 0) {
652                 LOGERR(klogErr, rc, "Failure to get '" OPTION_PRD "' argument");
653                 break;
654             }
655             if (pcount > 0) {
656                 const char *dummy = NULL;
657                 rc = ArgsOptionValue(args, OPTION_PRD, 0, (const void **)&dummy);
658                 if (rc) {
659                     LOGERR(klogErr, rc, "Failure to get '" OPTION_PRD "' argument");
660                     break;
661                 }
662                 if (tolower(dummy[0]) == 'y') {
663                     prm->proxyDisabled = eYes;
664                 }
665                 else if (tolower(dummy[0]) == 'n') {
666                     prm->proxyDisabled = eNo;
667                 }
668             }
669         }
670         {   // OPTION_PRX
671             rc = ArgsOptionCount(args, OPTION_PRX, &pcount);
672             if (rc != 0) {
673                 LOGERR(klogErr, rc, "Failure to get '" OPTION_PRX "' argument");
674                 break;
675             }
676             if (pcount > 0) {
677                 rc = ArgsOptionValue(args, OPTION_PRX, 0, (const void **)&prm->proxy);
678                 if (rc) {
679                     LOGERR(klogErr, rc, "Failure to get '" OPTION_PRX "' argument");
680                     break;
681                 }
682             }
683         }
684         {   // OPTION_DIR
685             rc = ArgsOptionCount(args, OPTION_DIR, &pcount);
686             if (rc != 0) {
687                 LOGERR(klogErr, rc, "Failure to get '" OPTION_DIR "' argument");
688                 break;
689             }
690             if (pcount) {
691                 prm->modeShowLoadPath = true;
692                 ++count;
693             }
694         }
695         {   // OPTION_ROOT
696             rc = ArgsOptionCount(args, OPTION_ROOT, &pcount);
697             if (rc != 0) {
698                 LOGERR(klogErr, rc, "Failure to get '" OPTION_ROOT "' argument");
699                 break;
700             }
701             if (pcount) {
702                 prm->modeRoot = true;
703             }
704         }
705         {   // OPTION_SET
706             rc = ArgsOptionCount(args, OPTION_SET, &pcount);
707             if (rc != 0) {
708                 LOGERR(klogErr, rc, "Failure to get '" OPTION_SET "' argument");
709                 break;
710             }
711             if (pcount) {
712                 rc = ArgsOptionValue(args, OPTION_SET, 0, (const void **)&prm->setValue);
713                 if (rc == 0) {
714                     const char* p = strchr(prm->setValue, '=');
715                     if (p == NULL || *(p + 1) == '\0') {
716                         rc = RC(rcExe, rcArgv, rcParsing, rcParam, rcInvalid);
717                         LOGERR(klogErr, rc, "Bad " OPTION_SET " value");
718                         break;
719                     }
720                     prm->modeSetNode = true;
721                     prm->modeCreate = prm->modeShowCfg = prm->modeShowEnv
722                         = prm->modeShowFiles = prm->modeShowLoadPath
723                         = prm->modeShowModules = false;
724                     count = 1;
725                 }
726             }
727         }
728         {   // OPTION_FIX
729             rc = ArgsOptionCount(args, OPTION_FIX, &pcount);
730             if (rc) {
731                 LOGERR(klogErr, rc, "Failure to get '" OPTION_FIX "' argument");
732                 break;
733             }
734             if (pcount) {
735                 prm->modeConfigure = true;
736                 prm->modeShowCfg = false;
737                 count = 1;
738                 prm->configureMode = eCfgModeDefault;
739             }
740         }
741 /* OPTION_PRTCT */ {
742             const char * option = OPTION_PRTCT;
743             rc = ArgsOptionCount(args, option, &pcount);
744             if (rc != 0) {
745                 PLOGERR(klogErr, (klogErr, rc,
746                     "Failure to get '${opt}' argument", "opt=%s", option));
747                 break;
748             }
749             if (pcount > 0)
750                 prm->ignoreProtected = true;
751         }
752 /* OPTION_CFG */
753         {
754             rc = ArgsOptionCount(args, OPTION_CFG, &pcount);
755             if (rc) {
756                 LOGERR(klogErr, rc, "Failure to get '" OPTION_CFG "' argument");
757                 break;
758             }
759             if (pcount) {
760 #if 1
761                 prm->modeConfigure = true;
762                 prm->modeShowCfg = false;
763                 count = 1;
764                 prm->configureMode = eCfgModeVisual;
765 
766 #else
767                 const char* dummy = NULL;
768                 rc = ArgsOptionValue(args, OPTION_CFG, 0, (const void **)&dummy);
769                 if (rc) {
770                     LOGERR(klogErr, rc, "Failure to get '" OPTION_CFG "' argument");
771                     break;
772                 }
773                 prm->modeConfigure = true;
774                 prm->modeShowCfg = false;
775                 count = 1;
776                 switch (dummy[0]) {
777                     case 't':
778                         prm->configureMode = eCfgModeTextual;
779                         break;
780                     default:
781                         prm->configureMode = eCfgModeDefault;
782                         break;
783                 }
784 #endif
785             }
786         }
787         /* OPTION_CFM */
788         {
789             rc = ArgsOptionCount(args, OPTION_CFM, &pcount);
790             if (rc) {
791                 LOGERR(klogErr, rc, "Failure to get '" OPTION_CFM "' argument");
792                 break;
793             }
794             if (pcount) {
795                 const char* dummy = NULL;
796                 size_t dummy_len;
797                 rc = ArgsOptionValue(args, OPTION_CFM, 0, (const void **)&dummy);
798                 if (rc) {
799                     LOGERR(klogErr, rc, "Failure to get '" OPTION_OUT "' argument");
800                     break;
801                 }
802                 prm->modeShowCfg = false;
803                 count = 1;
804                 prm->modeConfigure = true;
805 
806                 dummy_len = strlen( dummy );
807                 if ( dummy_len == 0 )
808                     dummy_len = 1;
809 
810                 if ( strncmp( dummy, "textual", dummy_len ) == 0 )
811                     prm->configureMode = eCfgModeTextual;
812                 else if ( strncmp( dummy, "graphical", dummy_len ) == 0 )
813                     prm->configureMode = eCfgModeVisual;
814                 else
815                 {
816                     rc = RC( rcExe, rcArgv, rcEvaluating, rcParam, rcInvalid );
817                     LOGERR(klogErr, rc, "Unrecognized '" OPTION_CFM "' argument");
818                     break;
819                 }
820             }
821         }
822 /********************************* cloud begin ********************************/
823 /* OPTION_C_IN */
824         {
825             rc = ArgsOptionCount(args, OPTION_C_IN, &pcount);
826             if (rc) {
827                 LOGERR(klogErr, rc,
828                     "Failure to get '" OPTION_C_IN "' argument");
829                 break;
830             }
831             if (pcount > 0)
832                 prm->cloudInfo = prm->modeCloud = true;
833         }
834 /* OPTION_C_RI */
835         {
836             rc = ArgsOptionCount(args, OPTION_C_RI, &pcount);
837             if (rc != 0) {
838                 LOGERR(klogErr, rc,
839                     "Failure to get '" OPTION_C_RI "' argument");
840                 break;
841             }
842             if (pcount > 0) {
843                 rc = ArgsOptionValue(args, OPTION_C_RI, 0,
844                     (const void **)&dummy);
845                 if (rc != 0) {
846                     LOGERR(klogErr, rc,
847                         "Failure to get '" OPTION_C_RI "' argument");
848                     break;
849                 }
850                 if (strncasecmp(dummy, "y", 1) == 0)
851                     prm->cloudReportIdentity = eTrue;
852                 else
853                     prm->cloudReportIdentity = eFalse;
854                 prm->modeCloud = true;
855             }
856         }
857 /* OPTION_GS_C */
858         {
859             rc = ArgsOptionCount(args, OPTION_GS_C, &pcount);
860             if (rc != 0) {
861                 LOGERR(klogErr, rc,
862                     "Failure to get '" OPTION_GS_C "' argument");
863                 break;
864             }
865             if (pcount > 0) {
866                 rc = ArgsOptionValue(args, OPTION_GS_C, 0,
867                     (const void **)&dummy);
868                 if (rc != 0) {
869                     LOGERR(klogErr, rc,
870                         "Failure to get '" OPTION_GS_C "' argument");
871                     break;
872                 }
873                 if (strcasecmp(dummy, "yes") == 0)
874                     prm->gsAcceptCharges = eTrue;
875                 else
876                     prm->gsAcceptCharges = eFalse;
877                 prm->modeCloud = true;
878             }
879         }
880 /* OPTION_GS_F */
881         {
882             rc = ArgsOptionCount(args, OPTION_GS_F, &pcount);
883             if (rc != 0) {
884                 LOGERR(klogErr, rc,
885                     "Failure to get '" OPTION_GS_F "' argument");
886                 break;
887             }
888             if (pcount > 0) {
889                 rc = ArgsOptionValue(args, OPTION_GS_F, 0, (const void **)
890                     &prm->gsCredentials);
891                 if (rc != 0) {
892                     LOGERR(klogErr, rc,
893                         "Failure to get '" OPTION_GS_F "' argument");
894                     break;
895                 }
896                 prm->modeCloud = true;
897             }
898         }
899 /* OPTION_S3_C */
900         {
901             rc = ArgsOptionCount(args, OPTION_S3_C, &pcount);
902             if (rc != 0) {
903                 LOGERR(klogErr, rc,
904                     "Failure to get '" OPTION_S3_C "' argument");
905                 break;
906             }
907             if (pcount > 0) {
908                 rc = ArgsOptionValue(args, OPTION_S3_C, 0,
909                     (const void **)&dummy);
910                 if (rc != 0) {
911                     LOGERR(klogErr, rc,
912                         "Failure to get '" OPTION_S3_C "' argument");
913                     break;
914                 }
915                 if (!strcasecmp(dummy, "yes"))
916                     prm->s3AcceptCharges = eTrue;
917                 else
918                     prm->s3AcceptCharges = eFalse;
919                 prm->modeCloud = true;
920             }
921         }
922 /* OPTION_S3_F */
923         {
924             rc = ArgsOptionCount(args, OPTION_S3_F, &pcount);
925             if (rc != 0) {
926                 LOGERR(klogErr, rc,
927                     "Failure to get '" OPTION_S3_F "' argument");
928                 break;
929             }
930             if (pcount > 0) {
931                 rc = ArgsOptionValue(args, OPTION_S3_F, 0, (const void **)
932                     &prm->s3Credentials);
933                 if (rc != 0) {
934                     LOGERR(klogErr, rc,
935                         "Failure to get '" OPTION_S3_F "' argument");
936                     break;
937                 }
938                 prm->modeCloud = true;
939             }
940         }
941 /* OPTION_S3_P */
942         {
943             rc = ArgsOptionCount(args, OPTION_S3_P, &pcount);
944             if (rc != 0) {
945                 LOGERR(klogErr, rc,
946                     "Failure to get '" OPTION_S3_P "' argument");
947                 break;
948             }
949             if (pcount > 0) {
950                 rc = ArgsOptionValue(args, OPTION_S3_P, 0, (const void **)
951                     &prm->s3Profile);
952                 if (rc != 0) {
953                     LOGERR(klogErr, rc,
954                         "Failure to get '" OPTION_S3_P "' argument");
955                     break;
956                 }
957                 prm->modeCloud = true;
958             }
959         }
960 /* OPTION_P_UR */
961         {
962             rc = ArgsOptionCount(args, OPTION_P_UR, &pcount);
963             if (rc != 0) {
964                 LOGERR(klogErr, rc,
965                     "Failure to get '" OPTION_P_UR "' argument");
966                 break;
967             }
968             if (pcount > 0) {
969                 prm->prefetchToCwd = eFalse;
970                 prm->modeCloud = true;
971             }
972         }
973 /* OPTION_P_CW */
974         {
975             rc = ArgsOptionCount(args, OPTION_P_CW, &pcount);
976             if (rc != 0) {
977                 LOGERR(klogErr, rc,
978                     "Failure to get '" OPTION_P_CW "' argument");
979                 break;
980             }
981             if (pcount > 0) {
982                 prm->prefetchToCwd = eTrue;
983                 prm->modeCloud = true;
984             }
985         }
986 /********************************* cloud end **********************************/
987    /* OPTION_ALL */
988         {
989             rc = ArgsOptionCount(args, OPTION_ALL, &pcount);
990             if (rc != 0) {
991                 LOGERR(klogErr, rc, "Failure to get '" OPTION_ALL "' argument");
992                 break;
993             }
994             if (pcount > 0
995                 || ( !prm->modeConfigure
996                     && !prm->ignoreProtected
997                     && !prm->modeShowCfg
998                     && ! prm->modeShowLoadPath
999                     && !prm->modeShowEnv
1000                     && !prm->modeShowFiles
1001                     && !prm->modeShowModules
1002                     && !prm->modeCreate
1003                     && !prm->modeSetNode
1004                     && !prm->modeCloud
1005                     && prm->ngc == NULL
1006                     && prm->proxy == NULL && prm->proxyDisabled == eUndefined))
1007                 /* show all by default */
1008             {
1009                 prm->modeShowCfg = prm->modeShowEnv = prm->modeShowFiles = true;
1010                 count += 2;
1011             }
1012         }
1013         if (count > 1) {
1014             prm->showMultiple = true;
1015         }
1016     } while (false);
1017 
1018     return rc;
1019 }
1020 
ParamsGetNextParam(Params * prm,const char ** param)1021 static rc_t ParamsGetNextParam(Params* prm, const char** param) {
1022     rc_t rc = 0;
1023     assert(prm && param);
1024     *param = NULL;
1025     if (prm->argsParamIdx < prm->argsParamCnt) {
1026         rc = ArgsParamValue(prm->args, prm->argsParamIdx++, (const void **)param);
1027         if (rc)
1028         {   LOGERR(klogErr, rc, "Failure retrieving query"); }
1029     }
1030     return rc;
1031 }
1032 
ParamsDestruct(Params * prm)1033 static rc_t ParamsDestruct(Params* prm) {
1034     rc_t rc = 0;
1035     assert(prm);
1036     RELEASE(Args, prm->args);
1037     return rc;
1038 }
1039 
1040 static
privReadStdinLine(char * buf,size_t bsize,bool destroy)1041 rc_t privReadStdinLine(char* buf, size_t bsize, bool destroy)
1042 {
1043     rc_t rc = 0;
1044     static const KFile* std_in = NULL;
1045     static uint64_t pos = 0;
1046     size_t num_read = 0;
1047     if (destroy) {
1048         RELEASE(KFile, std_in);
1049         pos = 0;
1050         return rc;
1051     }
1052     if (std_in == NULL) {
1053         rc = KFileMakeStdIn(&std_in);
1054         if (rc != 0) {
1055             DISP_RC(rc, "KFileMakeStdIn");
1056             return rc;
1057         }
1058     }
1059     rc = KFileRead(std_in, pos, buf, bsize, &num_read);
1060     DISP_RC(rc, "KFileRead");
1061     pos += num_read;
1062     if (num_read) {
1063         bool done = false;
1064         buf[num_read] = '\0';
1065         while (num_read > 0 && !done) {
1066             switch (buf[num_read - 1]) {
1067                 case '\n':
1068                 case '\r':
1069                     buf[--num_read] = '\0';
1070                     break;
1071                 default:
1072                     done = true;
1073                     break;
1074             }
1075         }
1076     }
1077     return rc;
1078 }
1079 
ReadStdinLine(char * buf,size_t bsize)1080 static rc_t ReadStdinLine(char* buf, size_t bsize) {
1081     return privReadStdinLine(buf, bsize, false);
1082 }
1083 
DestroyStdin(void)1084 static rc_t DestroyStdin(void)
1085 {   return privReadStdinLine(NULL, 0, true); }
1086 
In(const char * prompt,const char * def,char ** read)1087 static rc_t In(const char* prompt, const char* def, char** read) {
1088     rc_t rc = 0;
1089     char buf[PATH_MAX + 1];
1090     assert(prompt && read);
1091     *read = NULL;
1092     while (rc == 0 && (read[0] == NULL || read[0][0] == '\0')) {
1093         OUTMSG(("%s", prompt));
1094         if (def)
1095         {   OUTMSG((" [%s]", def)); }
1096         OUTMSG((": "));
1097         rc = ReadStdinLine(buf, sizeof buf);
1098         if (rc == 0) {
1099             while (strlen(buf) > 0) {
1100                 char c = buf[strlen(buf) - 1];
1101                 if (c == '\n' || c == '\r')
1102                 {   buf[strlen(buf) - 1] = '\0'; }
1103                 else
1104                 {   break; }
1105             }
1106             if (buf[0] == '\0' && def != NULL) {
1107                 string_copy_measure(buf, sizeof buf, def);
1108             }
1109             if (buf[0]) {
1110                 *read = strdup(buf);
1111                 if (*read == NULL) {
1112                     rc = RC
1113                         (rcExe, rcStorage, rcAllocating, rcMemory, rcExhausted);
1114                 }
1115             }
1116         }
1117     }
1118     return rc;
1119 }
1120 
scan_config_dir(const KDirectory * dir,uint32_t type,const char * name,void * data)1121 static rc_t CC scan_config_dir(const KDirectory* dir,
1122     uint32_t type, const char* name, void* data)
1123 {
1124     rc_t rc = 0;
1125     assert(data);
1126     switch (type) {
1127         case kptFile:
1128         case kptFile | kptAlias: {
1129             size_t sz = strlen(name);
1130             if (sz >= 5 && strcase_cmp(&name[sz - 4], 4, ".kfg", 4, 4) == 0) {
1131                 string_copy_measure(data, PATH_MAX + 1, name);
1132                                   /* from CreateConfig..KDirectoryVVisit call */
1133                 rc = RC(rcExe, rcDirectory, rcListing, rcFile, rcExists);
1134             }
1135             break;
1136         }
1137     }
1138     return rc;
1139 }
1140 
CreateConfig(char * argv0)1141 static rc_t CreateConfig(char* argv0) {
1142     const KFile* std_in = NULL;
1143     KDirectory* native = NULL;
1144     KDirectory* dir = NULL;
1145     rc_t rc = 0;
1146     char* location = NULL;
1147     char* mod = NULL;
1148     char* wmod = NULL;
1149     char* refseq = NULL;
1150     if (rc == 0) {
1151         rc = KDirectoryNativeDir(&native);
1152     }
1153     if (rc == 0) {
1154         const char* def = NULL;
1155         char cwd[PATH_MAX + 1] = "";
1156         const char* home = getenv("HOME");
1157         if (home)
1158         {   def = home; }
1159         else {
1160             rc = KDirectoryResolvePath ( native, true, cwd, sizeof cwd, "." );
1161             if (rc == 0 && cwd[0])
1162             {   def = cwd; }
1163             else
1164             {   def = "."; }
1165         }
1166         while (rc == 0) {
1167             char buffer[PATH_MAX + 1];
1168             rc = In("Specify configuration files directory", def, &location);
1169             if (rc == 0) {
1170                 rc = KDirectoryOpenDirUpdate(native, &dir, false, "%s", location);
1171                 if (rc == 0) {
1172                     rc = KDirectoryVisit
1173                         (dir, false, scan_config_dir, buffer, ".");
1174                     if (rc != 0) {
1175                         if (rc ==
1176                              RC(rcExe, rcDirectory, rcListing, rcFile, rcExists)
1177                             && buffer[0])
1178                         {
1179                             PLOGERR(klogErr, (klogErr, rc,
1180                                 "Configuration file found: $(dir)/$(name)",
1181                                 "dir=%s,name=%s", location, buffer));
1182                             rc = 0;
1183                             buffer[0] = '\0';
1184                             continue;
1185                         }
1186                         else {
1187                             PLOGERR(klogErr, (klogErr, rc, "$(dir)/$(name)",
1188                                 "dir=%s,name=%s", location, buffer));
1189                         }
1190                     }
1191                     break;
1192                 }
1193                 else if (GetRCObject(rc) == (enum RCObject)rcPath &&
1194                     (GetRCState(rc) == rcIncorrect || GetRCState(rc) == rcNotFound))
1195                 {
1196                     PLOGERR(klogErr,
1197                         (klogErr, rc, "$(path)", "path=%s", location));
1198                     rc = 0;
1199                 }
1200                 else { DISP_RC(rc, location); }
1201             }
1202         }
1203     }
1204     while (rc == 0) {
1205         const KDirectory* dir = NULL;
1206         rc = In("Specify refseq installation directory", NULL, &refseq);
1207         if (rc != 0)
1208         {   break; }
1209         rc = KDirectoryOpenDirRead(native, &dir, false, "%s", refseq);
1210         if (rc == 0) {
1211             RELEASE(KDirectory, dir);
1212             break;
1213         }
1214         else if (GetRCObject(rc) == (enum RCObject)rcPath
1215               && GetRCState(rc) == rcIncorrect)
1216         {
1217             PLOGERR(klogErr,
1218                 (klogErr, rc, "$(path)", "path=%s", refseq));
1219             rc = 0;
1220         }
1221         DISP_RC(rc, refseq);
1222     }
1223     if (rc == 0) {
1224         char buffer[512];
1225         const char path[] = "vdb-config.kfg";
1226         uint64_t pos = 0;
1227         KFile* f = NULL;
1228         rc = KDirectoryCreateFile(dir, &f, false, 0664, kcmCreate, "%s", path);
1229         DISP_RC(rc, path);
1230         if (rc == 0) {
1231             int n = snprintf(buffer, sizeof buffer,
1232                 "refseq/servers = \"%s\"\n", refseq);
1233             if (n >= sizeof buffer) {
1234                 rc = RC(rcExe, rcFile, rcWriting, rcBuffer, rcInsufficient);
1235             }
1236             else {
1237                 size_t num_writ = 0;
1238                 rc = KFileWrite(f, pos, buffer, strlen(buffer), &num_writ);
1239                 pos += num_writ;
1240             }
1241         }
1242         if (rc == 0) {
1243             const char buffer[] = "refseq/volumes = \".\"\n";
1244             size_t num_writ = 0;
1245             rc = KFileWrite(f, pos, buffer, strlen(buffer), &num_writ);
1246             pos += num_writ;
1247         }
1248         if (rc == 0 && mod && mod[0]) {
1249             int n = snprintf(buffer, sizeof buffer,
1250                 "vdb/module/paths = \"%s\"\n", mod);
1251             if (n >= sizeof buffer) {
1252                 rc = RC(rcExe, rcFile, rcWriting, rcBuffer, rcInsufficient);
1253             }
1254             else {
1255                 size_t num_writ = 0;
1256                 rc = KFileWrite(f, pos, buffer, strlen(buffer), &num_writ);
1257                 pos += num_writ;
1258             }
1259         }
1260         if (rc == 0 && wmod && wmod[0]) {
1261             int n = snprintf(buffer, sizeof buffer,
1262                 "vdb/wmodule/paths = \"%s\"\n", wmod);
1263             if (n >= sizeof buffer) {
1264                 rc = RC(rcExe, rcFile, rcWriting, rcBuffer, rcInsufficient);
1265             }
1266             else {
1267                 size_t num_writ = 0;
1268                 rc = KFileWrite(f, pos, buffer, strlen(buffer), &num_writ);
1269                 pos += num_writ;
1270             }
1271         }
1272         RELEASE(KFile, f);
1273     }
1274     free(mod);
1275     free(wmod);
1276     free(refseq);
1277     free(location);
1278     RELEASE(KDirectory, dir);
1279     RELEASE(KDirectory, native);
1280     RELEASE(KFile, std_in);
1281     DestroyStdin();
1282     return rc;
1283 }
1284 
1285 #if 0
1286 static rc_t ShowModules(const KConfig* cfg, const Params* prm) {
1287     rc_t rc = 0;
1288 #ifdef _STATIC
1289     OUTMSG(("<!-- Modules are not used in static build -->\n"));
1290 #else
1291     const VDBManager* mgr = NULL;
1292     KNamelist* list = NULL;
1293     OUTMSG(("<!-- Modules -->\n"));
1294     rc = VDBManagerMakeRead(&mgr, NULL);
1295     DISP_RC(rc, "while calling VDBManagerMakeRead");
1296     if (rc == 0) {
1297         rc = VDBManagerListExternalSchemaModules(mgr, &list);
1298         DISP_RC(rc, "while calling VDBManagerListExternalSchemaModules");
1299     }
1300     if (rc == 0) {
1301         uint32_t count = 0;
1302         rc = KNamelistCount(list, &count);
1303         DISP_RC(rc, "while calling KNamelistCount "
1304             "on VDBManagerListExternalSchemaModules result");
1305         if (rc == 0) {
1306             int64_t i = 0;
1307             for (i = 0; i < count && rc == 0; ++i) {
1308                 const char* name = NULL;
1309                 rc = KNamelistGet(list, i, &name);
1310                 DISP_RC(rc, "while calling KNamelistGet "
1311                     "on VDBManagerListExternalSchemaModules result");
1312                 if (rc == 0) {
1313                     OUTMSG(("%s\n", name));
1314                 }
1315             }
1316         }
1317     }
1318     OUTMSG(("\n"));
1319     RELEASE(KNamelist, list);
1320     RELEASE(VDBManager, mgr);
1321 #endif
1322     return rc;
1323 }
1324 #endif
1325 
KConfig_IgnoreProtected(KConfig * self)1326 static rc_t KConfig_IgnoreProtected(KConfig * self) {
1327     rc_t rc = KConfigWriteBool(self, "/repository/user/ignore-protected", true);
1328     if (rc == 0)
1329         rc = KConfigCommit(self);
1330     return rc;
1331 }
1332 
SetNode(KConfig * cfg,const Params * prm)1333 static rc_t SetNode(KConfig* cfg, const Params* prm) {
1334     rc_t rc = 0;
1335 
1336     KConfigNode* node = NULL;
1337     char* name = NULL;
1338     char* val  = NULL;
1339 
1340     assert(cfg && prm && prm->setValue);
1341 
1342     if (is_iser_an_admin() && !prm->modeRoot) {
1343         rc = RC(rcExe, rcNode, rcUpdating, rcCondition, rcViolated);
1344         LOGERR(klogErr, rc, "Warning: "
1345             "normally this application should not be run as root/superuser");
1346     }
1347 
1348     name = strdup(prm->setValue);
1349     if (name == NULL)
1350     {   return RC(rcExe, rcStorage, rcAllocating, rcMemory, rcExhausted); }
1351 
1352     val = strchr(name, '=');
1353     if (val == NULL || *(val + 1) == '\0') {
1354         rc_t rc = RC(rcExe, rcArgv, rcParsing, rcParam, rcInvalid);
1355         LOGERR(klogErr, rc, "Bad " OPTION_SET " value");
1356     }
1357 
1358     if (rc == 0) {
1359         *(val++) = '\0';
1360 
1361         rc = KConfigOpenNodeUpdate(cfg, &node, "%s", name);
1362         if (rc != 0) {
1363             PLOGERR(klogErr, (klogErr, rc,
1364                 "Cannot open node '$(name)' for update", "name=%s", name));
1365         }
1366     }
1367 
1368     if (rc == 0) {
1369         assert(val);
1370         rc = KConfigNodeWrite(node, val, strlen(val));
1371         if (rc != 0) {
1372             PLOGERR(klogErr, (klogErr, rc,
1373                 "Cannot write value '$(val) to node '$(name)'",
1374                 "val=%s,name=%s", val, name));
1375         }
1376     }
1377 
1378     if (rc == 0) {
1379         rc = KConfigCommit(cfg);
1380         DISP_RC(rc, "while calling KConfigCommit");
1381     }
1382 
1383     free(name);
1384     name = NULL;
1385 
1386     RELEASE(KConfigNode, node);
1387     return rc;
1388 }
1389 
SetProxy(KConfig * cfg,const Params * prm)1390 static rc_t SetProxy(KConfig *cfg, const Params *prm) {
1391     rc_t rc = 0;
1392 
1393     bool disabled = false;
1394     bool set = false;
1395     bool disableSet = false;
1396 
1397     assert(prm);
1398 
1399     switch (prm->proxyDisabled) {
1400         case eNo:
1401             disabled = false;
1402             break;
1403         case eYes:
1404             disabled = true;
1405             break;
1406         default:
1407             break;
1408     }
1409 
1410     if (prm->proxy != NULL) {
1411         rc = KConfig_Set_Http_Proxy_Path(cfg, prm->proxy);
1412         set = true;
1413 
1414         if (rc == 0 && prm->proxyDisabled == eUndefined) {
1415             rc = KConfig_Set_Http_Proxy_Enabled(cfg, true);
1416         }
1417     }
1418 
1419     if (prm->proxyDisabled != eUndefined) {
1420         rc_t r2 = KConfig_Set_Http_Proxy_Enabled(cfg, ! disabled);
1421         disableSet = true;
1422         if (r2 != 0 && rc == 0) {
1423             rc = r2;
1424         }
1425     }
1426 
1427     if (rc == 0) {
1428         rc = KConfigCommit(cfg);
1429         DISP_RC(rc, "while calling KConfigCommit");
1430     }
1431     if (rc == 0) {
1432         if (set) {
1433             OUTMSG(("Use HTTP proxy server configuration '%s'\n", prm->proxy));
1434         }
1435         if (disableSet) {
1436             OUTMSG(("HTTP proxy was %s\n", disabled ? "disabled" : "enabled"));
1437         }
1438     }
1439     else {
1440         LOGERR(klogErr, rc, "Failed to update HTTP proxy configuration");
1441     }
1442 
1443     return rc;
1444 }
1445 
ShowConfig(const KConfig * cfg,Params * prm)1446 static rc_t ShowConfig(const KConfig* cfg, Params* prm) {
1447     rc_t rc = 0;
1448     bool hasAny = false;
1449     bool hasQuery = false;
1450     bool xml = true;
1451     assert(cfg && prm);
1452     xml = prm->xml;
1453     while (rc == 0) {
1454         KNamelist* names = NULL;
1455         const KConfigNode* node = NULL;
1456         uint32_t count = 0;
1457         uint32_t i = 0;
1458         int indent = 0;
1459         const char* root = NULL;
1460         const char* nodeName = NULL;
1461         size_t nodeNameL = 1;
1462         rc = ParamsGetNextParam(prm, &root);
1463         if (rc == 0) {
1464             if (root == NULL) {
1465                 if (hasQuery)
1466                 {   break; }
1467                 else
1468                 {   root = "/"; }
1469             }
1470             else { hasQuery = true; }
1471             assert(root);
1472         }
1473         if (rc == 0) {
1474             int64_t len = strlen(root);
1475             assert(len > 0);
1476             while (len > 0) {
1477                 if (root[len - 1] == '/')
1478                 {   --len; }
1479                 else { break; }
1480             }
1481             assert(len >= 0);
1482             if (len == 0) {
1483                 root += strlen(root) - 1;
1484                 nodeName = root;
1485             }
1486             else {
1487                 char *c = memrchr(root, '/', len);
1488                 if (c != NULL) {
1489                     nodeName = c + 1;
1490                 }
1491                 else {
1492                     nodeName = root;
1493                 }
1494             }
1495             assert(nodeName && nodeName[0]);
1496             nodeNameL = strlen(nodeName);
1497             while (nodeNameL > 1 && nodeName[nodeNameL - 1] == '/')
1498             {   --nodeNameL; }
1499         }
1500 
1501         if (rc == 0) {
1502             rc = KConfigOpenNodeRead(cfg, &node, "%s", root);
1503             DISP_RC(rc, root);
1504         }
1505         if (rc == 0) {
1506             rc = KConfigNodeListChild(node, &names);
1507         }
1508         if (rc == 0) {
1509             rc = KNamelistCount(names, &count);
1510         }
1511         if (rc == 0 && count == 0) {
1512             char buf[512] = "";
1513             size_t num_read = 0;
1514             rc = KConfigNodeReadData(node, buf, sizeof buf, &num_read);
1515             if (rc == 0 && num_read > 0) {
1516                 if (prm->showMultiple)
1517                 {   OUTMSG(("<!-- Configuration node %s -->\n", root)); }
1518                 if (xml) {
1519                     VDB_CONGIG_OUTMSG(("<%.*s>", nodeNameL, nodeName));
1520                     VDB_CONGIG_OUTMSG(("%.*s", (int)num_read, buf));
1521                     VDB_CONGIG_OUTMSG(("</%.*s>\n", nodeNameL, nodeName));
1522                 }
1523                 else {
1524                     OUTMSG(("%.*s = \"%.*s\"\n",
1525                         nodeNameL, nodeName, (int)num_read, buf));
1526                 }
1527                 hasAny = true;
1528             }
1529         }
1530         else {
1531             if (rc == 0) {
1532                 if (nodeName[0] != '/') {
1533                     if (prm->showMultiple)
1534                     {   OUTMSG(("<!-- Configuration node %s -->\n", root)); }
1535                     VDB_CONGIG_OUTMSG(("<%.*s>\n", nodeNameL, nodeName));
1536                 } else {
1537                     if (prm->showMultiple)
1538                     {   OUTMSG(("<!-- Current configuration -->\n")); }
1539                     VDB_CONGIG_OUTMSG(("<Config>\n"));
1540                 }
1541                 hasAny = true;
1542                 ++indent;
1543             }
1544             for (i = 0; i < count && rc == 0; ++i) {
1545                 const char* name = NULL;
1546                 if (rc == 0)
1547                 {   rc = KNamelistGet(names, i, &name); }
1548                 if (rc == 0) {
1549                     char* fullname = NULL;
1550                     if (strcmp(root, "/") == 0) {
1551                         size_t bsize = strlen(name) + 2;
1552                         fullname = malloc(bsize);
1553                         if (fullname == NULL) {
1554                             rc = RC(rcExe,
1555                                 rcStorage, rcAllocating, rcMemory, rcExhausted);
1556                         }
1557                         string_printf(fullname, bsize, NULL, "/%s", name);
1558                     }
1559                     else {
1560                         size_t sz = strlen(root) + 2 + strlen(name);
1561                         size_t num_writ = 0;
1562                         fullname = malloc(sz);
1563                         if (fullname == NULL) {
1564                             rc = RC(rcExe,
1565                                 rcStorage, rcAllocating, rcMemory, rcExhausted);
1566                         }
1567                         rc = string_printf(fullname, sz, &num_writ,
1568                             "%s/%s", root, name);
1569                         assert(num_writ + 1 == sz);
1570                     }
1571                     if (rc == 0) {
1572                         rc = KConfigNodePrintChildNames
1573                             (xml, node, name, indent, fullname);
1574                         hasAny = true;
1575                     }
1576                     free(fullname);
1577                     fullname = NULL;
1578                 }
1579             }
1580             if (rc == 0) {
1581                 if (nodeName[0] != '/') {
1582                     VDB_CONGIG_OUTMSG(("</%.*s>\n", nodeNameL, nodeName));
1583                 }
1584                 else {
1585                     VDB_CONGIG_OUTMSG(("</Config>\n"));
1586                 }
1587             }
1588         }
1589 
1590         RELEASE(KConfigNode, node);
1591         RELEASE(KNamelist, names);
1592 
1593         if (rc == 0) {
1594             if (hasAny) {
1595                 OUTMSG(("\n"));
1596             }
1597             else if (nodeNameL > 0 && nodeName != NULL) {
1598                 VDB_CONGIG_OUTMSG(("<%.*s/>\n", nodeNameL, nodeName));
1599             }
1600         }
1601 
1602         if (!hasQuery)
1603         {   break; }
1604     }
1605 
1606     return rc;
1607 }
1608 
ShowFiles(const KConfig * cfg,const Params * prm)1609 static rc_t ShowFiles(const KConfig* cfg, const Params* prm) {
1610     rc_t rc = 0;
1611     bool hasAny = false;
1612     uint32_t count = 0;
1613     KNamelist* names = NULL;
1614     rc = KConfigListIncluded(cfg, &names);
1615     if (rc == 0) {
1616         rc = KNamelistCount(names, &count);
1617     }
1618     if (rc == 0) {
1619         uint32_t i = 0;
1620 
1621         if (prm->showMultiple) {
1622             if (prm->xml) {
1623                 OUTMSG(("<ConfigurationFiles>\n"));
1624             }
1625             else {
1626                 OUTMSG(("<!-- Configuration files -->\n"));
1627             }
1628             hasAny = true;
1629         }
1630 
1631         for (i = 0; i < count && rc == 0; ++i) {
1632             const char* name = NULL;
1633             if (rc == 0)
1634                 rc = KNamelistGet(names, i, &name);
1635             if (rc == 0) {
1636                 OUTMSG(("%s\n", name));
1637                 hasAny = true;
1638             }
1639         }
1640     }
1641     if (prm->showMultiple && prm->xml) {
1642         OUTMSG(("</ConfigurationFiles>"));
1643     }
1644 
1645     if (rc == 0 && hasAny) {
1646         OUTMSG(("\n"));
1647     }
1648 
1649     RELEASE(KNamelist, names);
1650 
1651     return rc;
1652 }
1653 
ShowEnv(const Params * prm)1654 static void ShowEnv(const Params* prm) {
1655     bool hasAny = false;
1656     const char * env_list [] = {
1657         "KLIB_CONFIG",
1658         "LD_LIBRARY_PATH",
1659         "NCBI_HOME",
1660         "NCBI_SETTINGS",
1661         "NCBI_VDB_CONFIG",
1662         "VDBCONFIG",
1663         "VDB_CONFIG",
1664     };
1665     int i = 0;
1666 
1667     if (prm->showMultiple) {
1668         if (prm->xml) {
1669             OUTMSG(("<Environment>\n"));
1670         }
1671         else {
1672             OUTMSG(("<!-- Environment -->\n"));
1673         }
1674         hasAny = true;
1675     }
1676 
1677     for (i = 0; i < sizeof env_list / sizeof env_list [ 0 ]; ++ i ) {
1678         const char *eval = getenv ( env_list [ i ] );
1679         if (eval) {
1680             OUTMSG(("%s=%s\n", env_list [ i ], eval));
1681             hasAny = true;
1682         }
1683     }
1684     if (prm->showMultiple && prm->xml) {
1685         OUTMSG(("</Environment>"));
1686     }
1687     if (hasAny) {
1688         OUTMSG(("\n"));
1689     }
1690     else {
1691         OUTMSG(("Environment variables are not found\n"));
1692     }
1693 }
1694 
_VFSManagerSystem2PosixPath(const VFSManager * self,const char * system,char posix[PATH_MAX])1695 static rc_t _VFSManagerSystem2PosixPath(const VFSManager *self,
1696     const char *system, char posix[PATH_MAX])
1697 {
1698     VPath *path = NULL;
1699     rc_t rc = VFSManagerMakeSysPath(self, &path, system);
1700     if (rc == 0) {
1701         size_t written;
1702         rc = VPathReadPath(path, posix, PATH_MAX, &written);
1703     }
1704     RELEASE(VPath, path);
1705     return rc;
1706 }
1707 
DefaultPepoLocation(const KConfig * cfg,uint32_t id,char * buffer,size_t bsize)1708 static rc_t DefaultPepoLocation(const KConfig *cfg,
1709     uint32_t id, char *buffer, size_t bsize)
1710 {
1711     rc_t rc = 0;
1712     char home[PATH_MAX] = "";
1713     size_t written = 0;
1714     assert(buffer && bsize);
1715     rc = KConfig_Get_Default_User_Path(cfg, home, sizeof home, &written);
1716     if (rc == 0 && written > 0) {
1717         rc = string_printf(buffer, bsize, &written, "%s/dbGaP-%u", home, id);
1718         if (rc == 0) {
1719             return rc;
1720         }
1721     }
1722 
1723     rc = KConfig_Get_Home(cfg, home, sizeof home, &written);
1724     if (rc == 0 && written > 0) {
1725         rc = string_printf(buffer, bsize, &written,
1726             "%s/ncbi/dbGaP-%u", home, id);
1727         if (rc == 0) {
1728             return rc;
1729         }
1730     }
1731 
1732     {
1733         VFSManager *vmgr = NULL;
1734         rc = VFSManagerMake(&vmgr);
1735         if (rc == 0) {
1736             const char *home = getenv("HOME");
1737             if (home == NULL) {
1738                 home = getenv("USERPROFILE");
1739             }
1740             if (home == NULL) {
1741 #define TODO 1
1742                 rc = TODO;
1743             }
1744             else {
1745                 size_t num_writ = 0;
1746                 char posix[PATH_MAX] = "";
1747                 rc = _VFSManagerSystem2PosixPath(vmgr, home, posix);
1748                 if (rc == 0) {
1749                     rc = string_printf(buffer, bsize, &num_writ,
1750                         "%s/ncbi/dbGaP-%u", posix, id);
1751                     if (rc == 0) {
1752                         return rc;
1753                     }
1754                 }
1755             }
1756         }
1757         RELEASE(VFSManager, vmgr);
1758     }
1759 
1760     return rc;
1761 }
1762 
DoImportNgc(KConfig * cfg,Params * prm,const char ** newRepoParentPath,uint32_t * result_flags)1763 static rc_t DoImportNgc(KConfig *cfg, Params *prm,
1764     const char **newRepoParentPath, uint32_t *result_flags)
1765 {
1766     rc_t rc = 0;
1767     KDirectory *dir = NULL;
1768     const KFile *src = NULL;
1769     const KNgcObj *ngc = NULL;
1770     static char buffer[PATH_MAX] = "";
1771     const char *root = NULL;
1772 
1773     assert(prm);
1774     if (rc == 0) {
1775         rc = KDirectoryNativeDir(&dir);
1776     }
1777     if (rc == 0) {
1778         rc = KDirectoryOpenFileRead(dir, &src, "%s", prm->ngc);
1779     }
1780     if (rc == 0) {
1781         rc = KNgcObjMakeFromFile(&ngc, src);
1782     }
1783     RELEASE(KFile, src);
1784 
1785     if (rc == 0) {
1786         uint32_t id = 0;
1787         rc = KNgcObjGetProjectId(ngc, &id);
1788         if (rc == 0) {
1789             const char *p = NULL;
1790             rc = ParamsGetNextParam(prm, &p);
1791             if (rc == 0 && p != NULL) {
1792                 rc = KDirectoryResolvePath(dir, true, buffer, sizeof buffer, p);
1793                 if (rc == 0) {
1794                     root = buffer;
1795                 }
1796             }
1797             else {
1798                 rc = DefaultPepoLocation(cfg, id, buffer, sizeof buffer);
1799                 if (rc == 0) {
1800                     root = buffer;
1801                 }
1802             }
1803         }
1804     }
1805     RELEASE(KDirectory, dir);
1806     if (rc == 0) {
1807         rc = KConfigImportNgc ( cfg, prm -> ngc, root, newRepoParentPath );
1808     }
1809     RELEASE(KNgcObj, ngc);
1810     return rc;
1811 }
1812 
ImportNgc(KConfig * cfg,Params * prm)1813 static rc_t ImportNgc(KConfig *cfg, Params *prm) {
1814     const char *newRepoParentPath = NULL;
1815     uint32_t result_flags = 0;
1816     rc_t rc = 0;
1817     assert(prm);
1818     rc = DoImportNgc(cfg, prm, &newRepoParentPath, &result_flags);
1819     DISP_RC2(rc, "cannot import ngc file", prm->ngc);
1820     if ( rc == 0 ) {
1821         rc = KConfigCommit(cfg);
1822     }
1823     if (rc == 0) {
1824 #if WINDOWS
1825         char ngcPath[PATH_MAX] = "";
1826         char system[MAX_PATH] = "";
1827 #endif
1828         KDirectory *wd = NULL;
1829         const char *ngc = prm->ngc;
1830         rc_t rc = KDirectoryNativeDir(&wd);
1831 #if WINDOWS
1832         if (rc == 0) {
1833             rc = KDirectoryPosixStringToSystemString(wd,
1834                 system, sizeof system, "%s", newRepoParentPath);
1835             if (rc == 0) {
1836                 newRepoParentPath = system;
1837             }
1838             rc = KDirectoryPosixStringToSystemString(wd,
1839                 ngcPath, sizeof ngcPath, "%s", ngc);
1840             if (rc == 0) {
1841                 ngc = ngcPath;
1842             }
1843         }
1844 #endif
1845         if (wd) {
1846             if (KDirectoryPathType(wd, newRepoParentPath)
1847                 == kptNotFound)
1848             {
1849                 KDirectoryCreateDir(wd, 0775,
1850                     kcmCreate | kcmParents, newRepoParentPath);
1851             }
1852         }
1853 
1854         OUTMSG ( ( "%s was imported.\nRepository directory is: '%s'.\n",
1855             ngc, newRepoParentPath ) );
1856         RELEASE(KDirectory, wd);
1857     }
1858     return rc;
1859 }
1860 
1861 static
CloudSetReportIdentity(KConfig * cfg,EState value,bool * set)1862 rc_t CloudSetReportIdentity(KConfig * cfg, EState value, bool * set) {
1863     rc_t rc = 0;
1864     if (value == eNotSet)
1865         return rc;
1866     rc = KConfig_Set_Report_Cloud_Instance_Identity(cfg, value == eTrue);
1867     if (rc == 0) {
1868         assert(set);
1869         *set = true;
1870         OUTMSG(("Report Cloud Instance Identity was set to %s\n",
1871             value == eTrue ? "true" : "false"));
1872     }
1873     return rc;
1874 }
1875 
1876 static
S3SetAcceptCharges(KConfig * cfg,EState value,bool * set)1877 rc_t S3SetAcceptCharges(KConfig * cfg, EState value, bool * set) {
1878     rc_t rc = 0;
1879     if (value == eNotSet)
1880         return rc;
1881     rc = KConfig_Set_User_Accept_Aws_Charges(cfg, value == eTrue);
1882     if (rc == 0) {
1883         assert(set);
1884         *set = true;
1885         OUTMSG(("Accept Charges for AWS Usage was set to %s\n",
1886             value == eTrue ? "true" : "false"));
1887     }
1888     return rc;
1889 }
1890 
S3SetCredentialsFile(KConfig * cfg,const char * aValue,bool * set)1891 static rc_t S3SetCredentialsFile(KConfig * cfg, const char * aValue,
1892     bool * set)
1893 {
1894     rc_t rc = 0;
1895     const char * value = aValue;
1896     if (value == NULL)
1897         return rc;
1898     if (value[0] == ' ' && value[1] == '\0')
1899         value = "";
1900     rc = KConfig_Set_Aws_Credential_File(cfg, value);
1901     if (rc == 0) {
1902         assert(set);
1903         *set = true;
1904         OUTMSG(("Path to AWS Credentials File was set to '%s'\n", value));
1905     }
1906     return rc;
1907 }
1908 
1909 static
S3SetProfile(KConfig * cfg,const char * aValue,bool * set)1910 rc_t S3SetProfile(KConfig * cfg, const char * aValue, bool * set)
1911 {
1912     rc_t rc = 0;
1913     const char * value = aValue;
1914     if (value == NULL)
1915         return rc;
1916     if (value[0] == ' ' && value[1] == '\0')
1917         value = "";
1918     rc = KConfig_Set_Aws_Profile(cfg, value);
1919     if (rc == 0) {
1920         assert(set);
1921         *set = true;
1922         OUTMSG(("AWS Profile was set to '%s'\n", value));
1923     }
1924     return rc;
1925 }
1926 
1927 static
GsSetAcceptCharges(KConfig * cfg,EState value,bool * set)1928 rc_t GsSetAcceptCharges(KConfig * cfg, EState value, bool * set)
1929 {
1930     rc_t rc = 0;
1931     if (value == eNotSet)
1932         return rc;
1933     rc = KConfig_Set_User_Accept_Gcp_Charges(cfg, value == eTrue);
1934     if (rc == 0) {
1935         assert(set);
1936         *set = true;
1937         OUTMSG(("Accept Charges for GCP Usage was set to %s\n",
1938             value == eTrue ? "true" : "false"));
1939     }
1940     return rc;
1941 }
1942 
GsSetCredentialsFile(KConfig * cfg,const char * aValue,bool * set)1943 static rc_t GsSetCredentialsFile(KConfig * cfg, const char * aValue,
1944     bool * set)
1945 {
1946     rc_t rc = 0;
1947     const char * value = aValue;
1948     if (value == NULL)
1949         return rc;
1950     if (value[0] == ' ' && value[1] == '\0')
1951         value = "";
1952     rc = KConfig_Set_Gcp_Credential_File(cfg, value);
1953     if (rc == 0) {
1954         assert(set);
1955         *set = true;
1956         OUTMSG(("Path to GCP Credentials File was set to '%s'\n", value));
1957     }
1958     return rc;
1959 }
1960 
1961 static
SetPrefetchDownload(KConfig * cfg,EState value,bool * set)1962 rc_t SetPrefetchDownload(KConfig * cfg, EState value, bool * set)
1963 {
1964     rc_t rc = 0;
1965     if (value == eNotSet)
1966         return rc;
1967     rc = KConfig_Set_Prefetch_Download_To_Cache(cfg, value == eFalse);
1968     if (rc == 0) {
1969         assert(set);
1970         *set = true;
1971         OUTMSG(("Prefetch will download to %s "
1972             "when Public User Repository is set\n",
1973             value == eTrue ? "Current Directory" : "User Repository"));
1974     }
1975     return rc;
1976 }
1977 
CloudInfo(const KConfig * cfg,const Params * prm)1978 static rc_t CloudInfo(const KConfig * cfg, const Params * prm) {
1979     bool value = false;
1980     char buff[PATH_MAX] = "";
1981 
1982     CloudMgr * mgr = NULL;
1983     rc_t rc = CloudMgrMake(&mgr, cfg, NULL);
1984 
1985     CloudProviderId cloud_provider = cloud_provider_none;
1986     rc = CloudMgrCurrentProvider(mgr, &cloud_provider);
1987 
1988     if (rc == 0 && cloud_provider != cloud_provider_none) {
1989         OUTMSG((
1990             "Cloud Environment:\n"
1991             "Current Cloud: %s\n", CloudProviderAsString(cloud_provider)));
1992     }
1993 
1994     if (rc == 0)
1995         OUTMSG(("Cloud Settings:\n\n"));
1996 
1997     if (rc == 0 && cloud_provider != cloud_provider_none) {
1998         rc = KConfig_Get_Report_Cloud_Instance_Identity(cfg, &value);
1999         if (rc == 0)
2000             OUTMSG(("Report Cloud Instance Identity: %s\n",
2001                 value ? "yes" : "no"));
2002     }
2003 
2004     if (rc == 0)
2005         OUTMSG(("AWS:\n"));
2006 
2007     if (rc == 0) {
2008         rc = KConfig_Get_User_Accept_Aws_Charges(cfg, &value);
2009         if (rc == 0)
2010             OUTMSG(("  Accept Charges for AWS Usage: %s\n",
2011                 value ? "yes" : "no"));
2012     }
2013 
2014     if (rc == 0) {
2015         rc = KConfig_Get_Aws_Credential_File(cfg, buff, sizeof buff, NULL);
2016         if (rc == 0 && buff[0] != '\0')
2017             OUTMSG(("  AWS Credentials File: '%s'\n", buff));
2018         else if (rc == SILENT_RC(rcKFG, rcNode, rcOpening, rcPath, rcNotFound))
2019             rc = 0;
2020     }
2021 
2022     if (rc == 0) {
2023         rc = KConfig_Get_Aws_Profile(cfg, buff, sizeof buff, NULL);
2024         if (rc == 0)
2025             OUTMSG(("  AWS Profile: '%s'\n", buff));
2026     }
2027 
2028     if (rc == 0)
2029         OUTMSG(("\nGCP:\n"));
2030 
2031     if (rc == 0) {
2032         rc = KConfig_Get_User_Accept_Gcp_Charges(cfg, &value);
2033         if (rc == 0)
2034             OUTMSG(("  Accept Charges for CGP Usage: %s\n",
2035                 value ? "yes" : "no"));
2036     }
2037 
2038     if (rc == 0) {
2039         rc = KConfig_Get_Gcp_Credential_File(cfg, buff, sizeof buff, NULL);
2040         if (rc == 0 && buff[0] != '\0')
2041             OUTMSG(("  GCP Credentials File: '%s'\n", buff));
2042         else if (rc == SILENT_RC(rcKFG, rcNode, rcOpening, rcPath, rcNotFound))
2043             rc = 0;
2044     }
2045 
2046     if (rc == 0) {
2047         OUTMSG(("\n\nTools:\n"));
2048         rc = KConfig_Get_Prefetch_Download_To_Cache(cfg, &value);
2049         if (rc == 0)
2050             OUTMSG(("  Prefetch downloads to %s\n",
2051                 value
2052                 ? "Public User Repository when it is set\n"
2053                 : "Current Directory when Public User Repository is set\n"));
2054     }
2055 
2056     if (rc == 0)
2057         OUTMSG(("\n"
2058             "To change Cloud-related Settings run:\n"
2059             "  vdb-config --interactive\n"
2060             "\n"
2061             "Cloud-related Command-Line Arguments:\n"
2062             "  vdb-config --cloud-info\n\n"));
2063     if (rc == 0 && cloud_provider != cloud_provider_none)
2064         OUTMSG((
2065             "  vdb-config --report-cloud-identity <yes|no>\n"));
2066     if (rc == 0)
2067         OUTMSG((
2068           "  vdb-config --accept-aws-charges <yes|no>\n"
2069           "  vdb-config --set-aws-credentials <Path to AWS Credentials File>\n"
2070           "  vdb-config --set-aws-profile <AWS Profile>\n"
2071           "  vdb-config --accept-gcp-charges <yes|no>\n"
2072           "  vdb-config --set-gcp-credentials <Path to GCP Credentials File>\n"
2073           "\n"
2074           "  vdb-config --prefetch-to-cwd\n"
2075           "  vdb-config --prefetch-to-user-repo\n"
2076           "\n"
2077           "  vdb-config --help\n"
2078             ));
2079 
2080     RELEASE(CloudMgr, mgr);
2081 
2082     return rc;
2083 }
2084 
ProcessCloud(KConfig * cfg,const Params * prm)2085 static rc_t ProcessCloud(KConfig * cfg, const Params * prm) {
2086     rc_t rc = 0;
2087 
2088     bool set = false;
2089 
2090     assert(prm);
2091 
2092     if (rc == 0)
2093         rc = CloudSetReportIdentity(cfg, prm->cloudReportIdentity, &set);
2094 
2095     if (rc == 0)
2096         rc = S3SetAcceptCharges(cfg, prm->s3AcceptCharges, &set);
2097 
2098     if (rc == 0)
2099         rc = S3SetCredentialsFile(cfg, prm->s3Credentials, &set);
2100 
2101     if (rc == 0)
2102         rc = S3SetProfile(cfg, prm->s3Profile, &set);
2103 
2104     if (rc == 0)
2105         rc = GsSetAcceptCharges(cfg, prm->gsAcceptCharges, &set);
2106 
2107     if (rc == 0)
2108         rc = GsSetCredentialsFile(cfg, prm->gsCredentials, &set);
2109 
2110     if (rc == 0)
2111         rc = SetPrefetchDownload(cfg, prm->prefetchToCwd, &set);
2112 
2113     if (rc == 0 && set )
2114         rc = KConfigCommit(cfg);
2115 
2116     if (rc == 0 && prm->cloudInfo)
2117         rc = CloudInfo(cfg, prm);
2118 
2119     return rc;
2120 }
2121 
KMain(int argc,char * argv[])2122 rc_t CC KMain(int argc, char* argv[]) {
2123     rc_t rc = 0;
2124 
2125     Params prm;
2126     KConfig* cfg = NULL;
2127     bool configured = false;
2128 
2129     if (rc == 0)
2130         rc = ParamsConstruct(argc, argv, &prm);
2131 
2132     if (rc == 0 && prm.showMultiple && prm.xml)
2133         OUTMSG(("<VdbConfig>\n"));
2134 
2135     if (rc == 0) {
2136         if (prm.modeConfigure) {
2137             rc = configure(prm.configureMode);
2138             configured = true;
2139         }
2140     }
2141 
2142     if (rc == 0) {
2143         const KDirectory *d = NULL;
2144         KDirectory * n = NULL;
2145         rc = KDirectoryNativeDir ( & n );
2146         if (prm.cfg_dir != NULL) {
2147             if (rc == 0) {
2148                 rc = KDirectoryOpenDirRead(n, &d, false, prm.cfg_dir);
2149                 DISP_RC2(rc, "while opening", prm.cfg_dir);
2150             }
2151         }
2152         if (rc == 0) {
2153             rc = KConfigMake(&cfg, d);
2154             DISP_RC(rc, "while calling KConfigMake");
2155         }
2156 
2157         if ( rc == 0 && ! configured ) {
2158             char home [ PATH_MAX ] = "";
2159             size_t written = 0;
2160             rc = KConfig_Get_Default_User_Path ( cfg, home, sizeof home,
2161                 & written );
2162             if ( rc == 0 ) {
2163                 char resolved [ PATH_MAX ] = "";
2164                 rc_t r2 = KDirectoryResolvePath ( n, true, resolved,
2165                     sizeof resolved, home );
2166                 if ( r2 == 0 ) {
2167                     size_t size  = string_measure ( home, NULL );
2168                     if ( string_cmp ( home, size, resolved,
2169                         string_measure ( resolved, NULL ), size ) != 0 )
2170                     {
2171                         r2 = KConfig_Set_Default_User_Path ( cfg, resolved );
2172                         if ( r2 == 0 ) {
2173                             KConfigCommit ( cfg );
2174                             KConfigRelease ( cfg );
2175                             rc = KConfigMake ( &cfg, d );
2176                             DISP_RC ( rc, "while re-calling KConfigMake" );
2177                         }
2178                     }
2179                 }
2180             }
2181             else
2182                 rc = 0;
2183         }
2184 
2185         RELEASE ( KDirectory, d );
2186         RELEASE ( KDirectory, n );
2187 
2188         if ( ! configured ) {
2189             if (prm.ngc)
2190                 rc = ImportNgc(cfg, &prm);
2191             else if (prm.modeSetNode) {
2192                 rc_t rc3 = SetNode(cfg, &prm);
2193                 if (rc3 != 0 && rc == 0)
2194                     rc = rc3;
2195             }
2196         }
2197 
2198         if (prm.proxy != NULL || prm.proxyDisabled != eUndefined) {
2199             rc_t rc3 = SetProxy(cfg, &prm);
2200             if (rc3 != 0 && rc == 0)
2201                 rc = rc3;
2202         }
2203 
2204         if (prm.modeShowCfg) {
2205             rc_t rc3 = ShowConfig(cfg, &prm);
2206             if (rc3 != 0 && rc == 0)
2207                 rc = rc3;
2208         }
2209 
2210         if (prm.modeShowFiles) {
2211             rc_t rc3 = ShowFiles(cfg, &prm);
2212             if (rc3 != 0 && rc == 0)
2213                 rc = rc3;
2214         }
2215 
2216         if (prm.modeShowLoadPath) {
2217             const char* path = NULL;
2218             rc_t rc3 = KConfigGetLoadPath(cfg, &path);
2219             if (rc3 == 0) {
2220                 if (path != NULL && path[0]) {
2221                     OUTMSG(("%s\n", path));
2222                 }
2223             }
2224             else if (rc == 0) {
2225                 rc = rc3;
2226             }
2227         }
2228 
2229         if (prm.modeCloud) {
2230             rc_t r = ProcessCloud(cfg, &prm);
2231             if (rc == 0 && r != 0)
2232                 rc = r;
2233         }
2234 
2235         if (prm.ignoreProtected) {
2236             rc_t r = KConfig_IgnoreProtected(cfg);
2237             if (rc == 0 && r != 0)
2238                 rc = r;
2239         }
2240     }
2241 
2242     if (prm.modeShowEnv) {
2243         ShowEnv(&prm);
2244     }
2245 
2246     if (rc == 0 && prm.showMultiple && prm.xml) {
2247         OUTMSG(("</VdbConfig>\n"));
2248     }
2249 
2250     RELEASE(KConfig, cfg);
2251 
2252     if (rc == 0 && prm.modeCreate) {
2253         rc = CreateConfig(argv[0]);
2254     }
2255 
2256     ParamsDestruct(&prm);
2257     return rc;
2258 }
2259 
2260 /************************************* EOF ************************************/
2261