LCOV - code coverage report
Current view: top level - progs - odbedit.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 1757 0
Test Date: 2025-11-11 10:26:08 Functions: 0.0 % 22 0

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         odbedit.cxx
       4              :   Created by:   Stefan Ritt
       5              : 
       6              :   Contents:     Command-line interface to the MIDAS online data base.
       7              : 
       8              :   $Id$
       9              : 
      10              : \********************************************************************/
      11              : 
      12              : #include "midas.h"
      13              : #include "mstrlcpy.h"
      14              : #include "msystem.h"
      15              : #include <stdio.h>
      16              : 
      17              : #include <assert.h>
      18              : #include <string>
      19              : 
      20              : extern INT cmd_edit(const char *prompt, char *cmd, INT (*dir)(char *, INT *), INT (*idle)());
      21              : 
      22              : BOOL need_redraw;
      23              : BOOL in_cmd_edit;
      24              : char pwd[256];
      25              : BOOL cmd_mode;
      26              : 
      27              : typedef struct {
      28              :    int flags;
      29              :    char pattern[32];
      30              :    int index;
      31              : } PRINT_INFO;
      32              : 
      33              : #define PI_LONG (1 << 0)
      34              : #define PI_RECURSIVE (1 << 1)
      35              : #define PI_VALUE (1 << 2)
      36              : #define PI_HEX (1 << 3)
      37              : #define PI_PAUSE (1 << 4)
      38              : 
      39              : MUTEX_T *tm;
      40              : 
      41              : /*------------------------------------------------------------------*/
      42              : 
      43            0 : INT thread(void *p) {
      44              :    char str[32];
      45              :    HNDLE hDB;
      46            0 :    cm_get_experiment_database(&hDB, NULL);
      47              :    do {
      48            0 :       sprintf(str, "%s", ss_tid_to_string(ss_gettid()).c_str());
      49            0 :       db_set_value(hDB, 0, "/Experiment/Name", str, sizeof(str), 1, TID_STRING);
      50              :    } while (1);
      51              : 
      52              :    return 0;
      53              : }
      54              : 
      55              : /*------------------------------------------------------------------*/
      56              : 
      57              : BOOL key_modified;
      58              : 
      59            0 : void key_update(HNDLE hDB, HNDLE hkey, void *info) {
      60            0 :    key_modified = TRUE;
      61            0 : }
      62              : 
      63              : /*------------------------------------------------------------------*/
      64              : 
      65            0 : void print_help(char *command) {
      66              : #ifndef OS_MSDOS /* save some DGROUP memory under MS-DOS */
      67            0 :    if (!command[0]) {
      68            0 :       printf("Database commands ([] are options, <> are placeholders):\n\n");
      69            0 :       printf("alarm                   - reset all alarms\n");
      70            0 :       printf("cd <dir>                - change current directory\n");
      71            0 :       printf("chat                    - enter chat mode\n");
      72            0 :       printf("chmod <mode> <key>      - change access mode of a key\n");
      73            0 :       printf("                          1=read | 2=write | 4=delete\n");
      74            0 :       printf("cleanup [client] [-f]   - delete hanging clients [force]\n");
      75            0 :       printf("copy <src> <dest>       - copy a subtree to a new location\n");
      76            0 :       printf("create <type> <key>     - create a key of a certain type\n");
      77            0 :       printf("create <type> <key>[n]  - create an array of size [n]\n");
      78            0 :       printf("create string <key>[n][m]  - create an array of [n] strings of [m] characters\n");
      79            0 :       printf("del/rm [-l] [-f] <key>  - delete a key and its subkeys\n");
      80            0 :       printf("  -l                      follow links\n");
      81            0 :       printf("  -f                      force deletion without asking\n");
      82            0 :       printf("exec <key>/<cmd>        - execute shell command (stored in key) on server\n");
      83            0 :       printf("exp <key> <filename>    - import key into ASCII file\n");
      84            0 :       printf("find <pattern>          - find a key with wildcard pattern\n");
      85            0 :       printf("help/? [command]        - print this help [for a specific command]\n");
      86            0 :       printf("hi [analyzer] [id]      - tell analyzer to clear histos\n");
      87            0 :       printf("imp <filename> [key]    - import ASCII file into string key\n");
      88            0 :       printf("json <odb path>         - print \"ODB save\" encoding of current directory or given odb path\n");
      89            0 :       printf("jsls                    - print \"ls\" encoding of current directory\n");
      90            0 :       printf("jsvalues                - print \"get_values\" encoding of current directory\n");
      91            0 :       printf("ln <source> <linkname>  - create a link to <source> key\n");
      92            0 :       printf("load <file>             - load database from .ODB file at current position\n");
      93            0 :       printf("-- hit return for more --\r");
      94            0 :       getchar();
      95            0 :       printf("ls/dir [-lhvrp] [<pat>] - show database entries which match pattern\n");
      96            0 :       printf("  -l                      detailed info\n");
      97            0 :       printf("  -h                      hex format\n");
      98            0 :       printf("  -v                      only value\n");
      99            0 :       printf("  -r                      show database entries recursively\n");
     100            0 :       printf("  -p                      pause between screens\n");
     101            0 :       printf("make [analyzer name]    - create experim.h\n");
     102            0 :       printf("mem [-v]                - show memeory usage [verbose]\n");
     103            0 :       printf("mkdir <subdir>          - make new <subdir>\n");
     104            0 :       printf("move <key> [top/bottom/[n]] - move key to position in keylist\n");
     105            0 :       printf("msg [user] <msg>        - send chat message (from interactive odbedit)\n");
     106            0 :       printf("msg <facility> <type> <name> <msg> - send message to [facility] log\n");
     107            0 :       printf("old [n]                 - display old n messages\n");
     108            0 :       printf("passwd                  - change MIDAS password\n");
     109            0 :       printf("pause                   - pause current run\n");
     110            0 :       printf("pwd                     - show current directory\n");
     111            0 :       printf("resume                  - resume current run\n");
     112            0 :       printf("rename <old> <new>      - rename key\n");
     113            0 :       printf("-- hit return for more --\r");
     114            0 :       getchar();
     115            0 :       printf("save [-c -s -x -j -cs] <file>  - save database at current position\n");
     116            0 :       printf("                          in ASCII format\n");
     117            0 :       printf("  -c                      as a C structure\n");
     118            0 :       printf("  -s                      as a #define'd string\n");
     119            0 :       printf("  -x                      as an XML file, or use file.xml\n");
     120            0 :       printf("  -j                      as a JSON file, or use file.json\n");
     121            0 :       printf("  -z                      as value-only JSON file\n");
     122            0 :       printf("set <key> <value>       - set the value of a key\n");
     123            0 :       printf("set <key>[i] <value>    - set the value of index i\n");
     124            0 :       printf("set <key>[*] <value>    - set the value of all indices of a key\n");
     125            0 :       printf("set <key>[i..j] <value> - set the value of all indices i..j\n");
     126            0 :       printf("scl [-w]                - show all active clients [with watchdog info]\n");
     127            0 :       printf("shutdown <client>/all   - shutdown individual or all clients\n");
     128            0 :       printf("sor                     - show open records in current subtree\n");
     129            0 :       printf("start [number][now][-v] - start a run [with a specific number],\n");
     130            0 :       printf("                          [now] w/o asking parameters, [-v] debug output\n");
     131            0 :       printf("stop [-v]               - stop current run, [-v] debug output\n");
     132            0 :       printf("test_rpc                - test mserver RPC connection and parameter encoding and decoding\n");
     133            0 :       printf("trunc <key> <index>     - truncate key to [index] values\n");
     134            0 :       printf("ver                     - show MIDAS library version\n");
     135            0 :       printf("webpasswd               - change WWW password for mhttpd\n");
     136            0 :       printf("wait <key>              - wait for key to get modified\n");
     137            0 :       printf("watch <key>             - watch key or ODB tree to be modified\n");
     138              : 
     139            0 :       printf("\nquit/exit               - exit\n");
     140            0 :       return;
     141              :    }
     142              : 
     143            0 :    if (equal_ustring(command, "cd")) {
     144            0 :       printf("cd <dir> - change current directory. Use \"cd /\" to change to the root\n");
     145            0 :       printf("           of the ODB, \"cd ..\" to change to the parent directory.\n");
     146            0 :    } else if (equal_ustring(command, "chat")) {
     147            0 :       printf("chat - enter chat mode. In this mode, users can \"talk\" to each other.\n");
     148            0 :       printf("       Each user running ODBEdit connected to the same experiment can see\n");
     149            0 :       printf("       the other messages and each user running ODBEdit in chat mode can\n");
     150            0 :       printf("       produce messages. All messages are logged in the MIDAS logging file.\n");
     151              :    } else
     152            0 :       printf("No specific help available for command \"%s\".\n", command);
     153              : 
     154              : #endif
     155              : }
     156              : 
     157              : /*------------------------------------------------------------------*/
     158              : 
     159            0 : void process_message(HNDLE hBuf, HNDLE id, EVENT_HEADER *pheader, void *message) {
     160              :    time_t tm;
     161              :    char str[80];
     162              : 
     163              :    /* prepare time */
     164            0 :    time(&tm);
     165              :    assert(sizeof(str) >= 32);
     166            0 :    ctime_r(&tm, str);
     167            0 :    str[19] = 0;
     168              : 
     169              :    /* print message text which comes after event header */
     170            0 :    if (in_cmd_edit)
     171            0 :       printf("\r%s %s\n", str + 11, (char *) message);
     172              :    else
     173            0 :       printf("\n%s %s\n", str + 11, (char *) message);
     174              : 
     175            0 :    need_redraw = TRUE;
     176            0 : }
     177              : 
     178            0 : int print_message(const char *msg) {
     179            0 :    if (in_cmd_edit)
     180            0 :       printf("\r%s\n", msg);
     181              :    else
     182            0 :       printf("%s\n", msg);
     183              : 
     184            0 :    need_redraw = TRUE;
     185            0 :    return 0;
     186              : }
     187              : 
     188              : /*------------------------------------------------------------------*/
     189              : 
     190            0 : BOOL match(char *pat, char *str)
     191              : /* process a wildcard match */
     192              : {
     193            0 :    if (!*str)
     194            0 :       return *pat == '*' ? match(pat + 1, str) : !*pat;
     195              : 
     196            0 :    switch (*pat) {
     197            0 :       case '\0':
     198            0 :          return 0;
     199            0 :       case '*':
     200            0 :          return match(pat + 1, str) || match(pat, str + 1);
     201            0 :       case '?':
     202            0 :          return match(pat + 1, str + 1);
     203            0 :       default:
     204            0 :          return (toupper(*pat) == toupper(*str)) && match(pat + 1, str + 1);
     205              :    }
     206              : }
     207              : 
     208              : /*------------------------------------------------------------------*/
     209              : 
     210              : int ls_line, ls_abort;
     211              : 
     212            0 : BOOL check_abort(int flags, int l) {
     213              :    int c;
     214              : 
     215            0 :    if ((flags & PI_PAUSE) && (l % 24) == 23) {
     216            0 :       printf("Press any key to continue or q to quit ");
     217            0 :       fflush(stdout);
     218              :       do {
     219            0 :          c = ss_getchar(0);
     220            0 :          if (c == 'q') {
     221            0 :             printf("\n");
     222            0 :             ls_abort = TRUE;
     223            0 :             return TRUE;
     224            0 :          } else if (c > 0) {
     225            0 :             printf("\r                                        \r");
     226            0 :             return FALSE;
     227              :          }
     228              : 
     229            0 :          int status = cm_yield(100);
     230            0 :          if (status == SS_ABORT || status == RPC_SHUTDOWN)
     231              :             break;
     232              : 
     233            0 :       } while (!cm_is_ctrlc_pressed());
     234              :    }
     235              : 
     236            0 :    if (cm_is_ctrlc_pressed()) {
     237            0 :       ls_abort = TRUE;
     238            0 :       return TRUE;
     239              :    }
     240              : 
     241            0 :    return FALSE;
     242              : }
     243              : 
     244            0 : static void pad_to_pos(std::string *s, size_t pos) {
     245            0 :    while (s->length() < pos)
     246            0 :       (*s) += " ";
     247            0 : }
     248              : 
     249            0 : INT print_key(HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info) {
     250              :    INT i, status;
     251              :    DWORD delta;
     252              :    PRINT_INFO *pi;
     253              :    KEY key;
     254              : 
     255            0 :    if (ls_abort)
     256            0 :       return 0;
     257              : 
     258            0 :    pi = (PRINT_INFO *) info;
     259            0 :    memcpy(&key, pkey, sizeof(KEY));
     260              : 
     261              :    /* if pattern set, check if match */
     262            0 :    if (pi->pattern[0] && !match(pi->pattern, pkey->name))
     263            0 :       return SUCCESS;
     264              : 
     265            0 :    if (pi->flags & PI_VALUE) {
     266              :       /* only print value */
     267            0 :       if (key.type != TID_KEY) {
     268            0 :          assert(key.total_size > 0);
     269            0 :          char *buf = (char *) malloc(key.total_size);
     270            0 :          int size = key.total_size;
     271            0 :          status = db_get_link_data(hDB, hKey, buf, &size, key.type);
     272              : 
     273            0 :          std::string xdata_str;
     274              : 
     275              :          /* resolve links */
     276            0 :          if (key.type == TID_LINK) {
     277            0 :             if (strlen(buf) > 0 && buf[strlen(buf) - 1] == ']')
     278            0 :                status = DB_SUCCESS;
     279              :             else
     280            0 :                status = db_find_key(hDB, 0, buf, &hKey);
     281            0 :             if (status == DB_SUCCESS) {
     282            0 :                status = db_get_key(hDB, hKey, &key);
     283            0 :                if (status == DB_SUCCESS) {
     284            0 :                   assert(key.total_size > 0);
     285            0 :                   buf = (char *) realloc(buf, key.total_size);
     286            0 :                   size = key.total_size;
     287            0 :                   if (key.type != TID_KEY)
     288            0 :                      status = db_get_data(hDB, hKey, buf, &size, key.type);
     289              :                   else
     290            0 :                      status = DB_TYPE_MISMATCH;
     291              :                }
     292              :             }
     293              :          }
     294              : 
     295            0 :          if (status == DB_NO_KEY)
     296            0 :             xdata_str = "<cannot resolve link>";
     297            0 :          else if (status == DB_NO_ACCESS)
     298            0 :             xdata_str = "<no read access>";
     299              :          else
     300            0 :             for (i = 0; i < key.num_values; i++) {
     301            0 :                if (pi->flags & PI_HEX)
     302            0 :                   xdata_str = db_sprintfh(buf, key.item_size, i, key.type);
     303              :                else
     304            0 :                   xdata_str = db_sprintf(buf, key.item_size, i, key.type);
     305              : 
     306            0 :                if ((pi->index != -1 && i == pi->index) || pi->index == -1)
     307            0 :                   printf("%s\n", xdata_str.c_str());
     308            0 :                if (check_abort(pi->flags, ls_line++))
     309            0 :                   return 0;
     310              :             }
     311            0 :          free(buf);
     312            0 :       }
     313              :    } else {
     314              :       /* print key name with value */
     315              :       //memset(line, ' ', sizeof(line));
     316              :       //line[sizeof(line)-1] = 0;
     317              :       //sprintf(line + level * 4, "%s", key.name);
     318            0 :       std::string xline;
     319            0 :       pad_to_pos(&xline, level * 4);
     320            0 :       xline += key.name;
     321            0 :       if (key.type == TID_LINK) {
     322            0 :          if (key.total_size > 0) {
     323            0 :             char *buf = (char *) malloc(key.total_size);
     324            0 :             int size = key.total_size;
     325            0 :             db_get_link_data(hDB, hKey, buf, &size, key.type);
     326              :             //sprintf(line + strlen(line), " -> %s", buf);
     327            0 :             xline += " -> ";
     328            0 :             xline += buf;
     329            0 :             free(buf);
     330              :          } else {
     331              :             //sprintf(line + strlen(line), " -> (empty)");
     332            0 :             xline += " -> (empty)";
     333              :          }
     334            0 :          if (pi->index != -1) {
     335              :             //sprintf(line + strlen(line), "[%d]", pi->index);
     336            0 :             xline += "[";
     337            0 :             xline += std::to_string(pi->index);
     338            0 :             xline += "]";
     339              :          }
     340            0 :          if (xline.length() >= 32) {
     341            0 :             printf("%s\n", xline.c_str());
     342            0 :             xline = "";
     343              :          } else {
     344              :             //line[strlen(line)] = ' ';
     345            0 :             xline += " ";
     346              :          }
     347              :       } else {
     348            0 :          if (pi->index != -1) {
     349              :             //sprintf(line + strlen(line), "[%d]", pi->index);
     350              :          }
     351              :          //line[strlen(line)] = ' ';
     352            0 :          xline += " ";
     353              :       }
     354              : 
     355            0 :       if (key.type == TID_KEY) {
     356            0 :          if (pi->flags & PI_LONG) {
     357              :             //sprintf(line + 32, "DIR");
     358            0 :             pad_to_pos(&xline, 32);
     359            0 :             xline += "DIR";
     360              :          }
     361            0 :          printf("%s\n", xline.c_str());
     362            0 :          if (check_abort(pi->flags, ls_line++))
     363            0 :             return 0;
     364              :       } else {
     365            0 :          char *data_buf = NULL;
     366              : 
     367            0 :          if (key.total_size > 0) {
     368            0 :             data_buf = (char *) malloc(key.total_size);
     369            0 :             int size = key.total_size;
     370            0 :             status = db_get_link_data(hDB, hKey, data_buf, &size, key.type);
     371              :          } else {
     372            0 :             status = DB_SUCCESS;
     373              :          }
     374              : 
     375            0 :          std::string xdata_str;
     376              : 
     377              :          /* resolve links */
     378            0 :          if (key.type == TID_LINK && data_buf) {
     379            0 :             if (strlen(data_buf) > 0 && data_buf[strlen(data_buf) - 1] == ']')
     380            0 :                status = DB_SUCCESS;
     381              :             else
     382            0 :                status = db_find_key(hDB, 0, data_buf, &hKey);
     383            0 :             if (status == DB_SUCCESS) {
     384            0 :                status = db_get_key(hDB, hKey, &key);
     385            0 :                if (status == DB_SUCCESS) {
     386            0 :                   if (key.total_size > 0) {
     387            0 :                      data_buf = (char *) realloc(data_buf, key.total_size);
     388            0 :                      int size = key.total_size;
     389            0 :                      if (key.type != TID_KEY)
     390            0 :                         status = db_get_data(hDB, hKey, data_buf, &size, key.type);
     391              :                      else
     392            0 :                         status = DB_TYPE_MISMATCH;
     393              :                   } else {
     394            0 :                      if (data_buf)
     395            0 :                         free(data_buf);
     396            0 :                      data_buf = NULL;
     397              :                   }
     398              :                }
     399              :             }
     400              :          }
     401              : 
     402            0 :          if (status == DB_TYPE_MISMATCH)
     403            0 :             xdata_str = "<subdirectory>";
     404            0 :          else if (status == DB_NO_KEY || status == DB_INVALID_LINK)
     405            0 :             xdata_str = "<cannot resolve link>";
     406            0 :          else if (status == DB_NO_ACCESS)
     407            0 :             xdata_str = "<no read access>";
     408            0 :          else if (!data_buf)
     409            0 :             xdata_str = "<empty>";
     410              :          else {
     411            0 :             if (pi->flags & PI_HEX)
     412            0 :                xdata_str += db_sprintfh(data_buf, key.item_size, 0, key.type);
     413              :             else
     414            0 :                xdata_str += db_sprintf(data_buf, key.item_size, 0, key.type);
     415              :          }
     416              : 
     417            0 :          if (pi->flags & PI_LONG) {
     418              :             //sprintf(line + 32, "%s", rpc_tid_name(key.type));
     419              :             //line[strlen(line)] = ' ';
     420              :             //sprintf(line + 40, "%d", key.num_values);
     421              :             //line[strlen(line)] = ' ';
     422              :             //sprintf(line + 46, "%d", key.item_size);
     423              :             //line[strlen(line)] = ' ';
     424            0 :             pad_to_pos(&xline, 32);
     425            0 :             xline += rpc_tid_name(key.type);
     426            0 :             pad_to_pos(&xline, 40);
     427            0 :             xline += std::to_string(key.num_values);
     428            0 :             pad_to_pos(&xline, 46);
     429            0 :             xline += std::to_string(key.item_size);
     430              : 
     431            0 :             db_get_key_time(hDB, hKey, &delta);
     432              : 
     433              :             //if (delta < 60)
     434              :             //   sprintf(line + 52, "%ds", delta);
     435              :             //else if (delta < 3600)
     436              :             //   sprintf(line + 52, "%1.0lfm", delta / 60.0);
     437              :             //else if (delta < 86400)
     438              :             //   sprintf(line + 52, "%1.0lfh", delta / 3600.0);
     439              :             //else if (delta < 86400 * 99)
     440              :             //   sprintf(line + 52, "%1.0lfh", delta / 86400.0);
     441              :             //else
     442              :             //   sprintf(line + 52, ">99d");
     443              :             //line[strlen(line)] = ' ';
     444              : 
     445            0 :             pad_to_pos(&xline, 52);
     446            0 :             if (delta < 60)
     447            0 :                xline += msprintf("%ds", delta);
     448            0 :             else if (delta < 3600)
     449            0 :                xline += msprintf("%1.0lfm", delta / 60.0);
     450            0 :             else if (delta < 86400)
     451            0 :                xline += msprintf("%1.0lfh", delta / 3600.0);
     452            0 :             else if (delta < 86400 * 99)
     453            0 :                xline += msprintf("%1.0lfh", delta / 86400.0);
     454              :             else
     455            0 :                xline += ">99d";
     456              : 
     457              :             //sprintf(line + 57, "%d", key.notify_count);
     458              :             //line[strlen(line)] = ' ';
     459            0 :             pad_to_pos(&xline, 57);
     460            0 :             xline += std::to_string(key.notify_count);
     461              : 
     462            0 :             pad_to_pos(&xline, 60);
     463            0 :             if (key.access_mode & MODE_READ)
     464            0 :                xline += 'R';
     465              :             else
     466            0 :                xline += ' ';
     467              : 
     468            0 :             if (key.access_mode & MODE_WRITE)
     469            0 :                xline += 'W';
     470              :             else
     471            0 :                xline += ' ';
     472              : 
     473            0 :             if (key.access_mode & MODE_DELETE)
     474            0 :                xline += 'D';
     475              :             else
     476            0 :                xline += ' ';
     477              : 
     478            0 :             if (key.access_mode & MODE_EXCLUSIVE)
     479            0 :                xline += 'E';
     480              :             else
     481            0 :                xline += ' ';
     482              : 
     483            0 :             pad_to_pos(&xline, 66);
     484            0 :             if (key.type == TID_STRING && strchr(xdata_str.c_str(), '\n'))
     485            0 :                xline += "<multi-line>";
     486            0 :             else if (key.num_values == 1)
     487            0 :                xline += xdata_str;
     488            0 :          } else if (key.num_values == 1) {
     489            0 :             pad_to_pos(&xline, 32);
     490            0 :             if (key.type == TID_STRING && strchr(xdata_str.c_str(), '\n'))
     491            0 :                xline += "<multi-line>";
     492              :             else
     493            0 :                xline += xdata_str;
     494              :          }
     495              : 
     496            0 :          if (!xline.empty())
     497            0 :             printf("%s\n", xline.c_str());
     498              : 
     499            0 :          if (key.type == TID_STRING && strchr(xdata_str.c_str(), '\n'))
     500            0 :             puts(xdata_str.c_str());
     501              : 
     502            0 :          if (check_abort(pi->flags, ls_line++))
     503            0 :             return 0;
     504              : 
     505            0 :          if (key.num_values > 1) {
     506            0 :             for (i = 0; i < key.num_values; i++) {
     507            0 :                if (data_buf) {
     508            0 :                   if (pi->flags & PI_HEX)
     509            0 :                      xdata_str = db_sprintfh(data_buf, key.item_size, i, key.type);
     510              :                   else
     511            0 :                      xdata_str = db_sprintf(data_buf, key.item_size, i, key.type);
     512              :                } else {
     513            0 :                   xdata_str = "<empty>";
     514              :                }
     515              : 
     516            0 :                std::string yline;
     517              : 
     518            0 :                if (pi->flags & PI_LONG) {
     519              :                   //sprintf(line + 40, "[%d]", i);
     520            0 :                   pad_to_pos(&yline, 40);
     521            0 :                   yline += "[";
     522            0 :                   yline += std::to_string(i);
     523            0 :                   yline += "]";
     524              : 
     525            0 :                   pad_to_pos(&yline, 56);
     526            0 :                   yline += xdata_str;
     527              :                } else {
     528            0 :                   pad_to_pos(&yline, 32);
     529            0 :                   yline += xdata_str;
     530              :                }
     531              : 
     532            0 :                if ((pi->index != -1 && i == pi->index) || pi->index == -1)
     533            0 :                   printf("%s\n", yline.c_str());
     534              : 
     535            0 :                if (check_abort(pi->flags, ls_line++))
     536            0 :                   return 0;
     537            0 :             }
     538              :          }
     539            0 :          if (data_buf)
     540            0 :             free(data_buf);
     541            0 :       }
     542            0 :    }
     543              : 
     544            0 :    return SUCCESS;
     545              : }
     546              : 
     547              : /*------------------------------------------------------------------*/
     548              : 
     549            0 : void set_key(HNDLE hDB, HNDLE hKey, int index1, int index2, char *value) {
     550              :    KEY key;
     551              :    char data[1000];
     552            0 :    int i, size, status = 0;
     553              : 
     554            0 :    db_get_link(hDB, hKey, &key);
     555              : 
     556            0 :    memset(data, 0, sizeof(data));
     557            0 :    db_sscanf(value, data, &size, 0, key.type);
     558              : 
     559              :    /* extend data size for single string if necessary */
     560            0 :    if ((key.type == TID_STRING || key.type == TID_LINK)
     561            0 :        && (int) strlen(data) + 1 > key.item_size && key.num_values == 1)
     562            0 :       key.item_size = strlen(data) + 1;
     563              : 
     564            0 :    if (key.item_size == 0)
     565            0 :       key.item_size = rpc_tid_size(key.type);
     566              : 
     567            0 :    if (key.num_values > 1 && index1 == -1) {
     568            0 :       for (i = 0; i < key.num_values; i++)
     569            0 :          status = db_set_link_data_index(hDB, hKey, data, key.item_size, i, key.type);
     570            0 :    } else if (key.num_values > 1 && index2 > index1) {
     571            0 :       for (i = index1; i < key.num_values && i <= index2; i++)
     572            0 :          status = db_set_link_data_index(hDB, hKey, data, key.item_size, i, key.type);
     573            0 :    } else if (key.num_values > 1 || index1 > 0)
     574            0 :       status = db_set_link_data_index(hDB, hKey, data, key.item_size, index1, key.type);
     575              :    else
     576            0 :       status = db_set_link_data(hDB, hKey, data, key.item_size, 1, key.type);
     577              : 
     578            0 :    if (status == DB_NO_ACCESS)
     579            0 :       printf("Write access not allowed\n");
     580            0 : }
     581              : 
     582              : /*------------------------------------------------------------------*/
     583              : 
     584              : #if 0
     585              : // scan_tree() is not used anywhere, best I can tell. K.O. Aug2024
     586              : void scan_tree(HNDLE hDB, HNDLE hKey, INT * total_size_key, INT * total_size_data,
     587              :                INT level, INT flags)
     588              : {
     589              :    INT i, j;
     590              :    //INT size;
     591              :    INT status;
     592              :    KEY key;
     593              :    HNDLE hSubkey;
     594              :    static char data_str[256], line[256];
     595              :    DWORD delta;
     596              : 
     597              :    if (cm_is_ctrlc_pressed()) {
     598              :       if (level == 0)
     599              :          cm_ack_ctrlc_pressed();
     600              :       return;
     601              :    }
     602              : 
     603              :    db_get_key(hDB, hKey, &key);
     604              : 
     605              :    *total_size_key += ALIGN8(sizeof(KEY));
     606              :    if (key.type == TID_KEY)
     607              :       *total_size_key += ALIGN8(sizeof(KEYLIST));
     608              :    else
     609              :       *total_size_data += ALIGN8(key.total_size);
     610              : 
     611              :    if (flags & 0x4) {
     612              :       /* only print value */
     613              :       if (key.type != TID_KEY) {
     614              :          assert(key.total_size > 0);
     615              :          char* buf = (char*)malloc(key.total_size);
     616              :          int size = key.total_size;
     617              :          status = db_get_data(hDB, hKey, buf, &size, key.type);
     618              :          if (status == DB_NO_ACCESS)
     619              :             strcpy(data_str, "<no read access>");
     620              :          else
     621              :             for (j = 0; j < key.num_values; j++) {
     622              :                std::string data_str;
     623              :                if (flags & 0x8)
     624              :                   data_str = db_sprintfh(buf, key.item_size, j, key.type);
     625              :                else
     626              :                   data_str = db_sprintf(buf, key.item_size, j, key.type);
     627              :                printf("%s\n", data_str.c_str());
     628              :             }
     629              :          free(buf);
     630              :       }
     631              :    } else {
     632              :       printf("XXX here!\n");
     633              :       /* print key name with value */
     634              :       memset(line, ' ', 80);
     635              :       line[80] = 0;
     636              :       sprintf(line + level * 4, "%s", key.name);
     637              :       line[strlen(line)] = ' ';
     638              : 
     639              :       if (key.type == TID_KEY) {
     640              :          line[32] = 0;
     641              :          printf("%s\n", line);
     642              :       } else {
     643              :          assert(key.total_size > 0);
     644              :          char* buf = (char*)malloc(key.total_size);
     645              :          int size = key.total_size;
     646              :          status = db_get_data(hDB, hKey, buf, &size, key.type);
     647              :          if (status == DB_NO_ACCESS)
     648              :             strcpy(data_str, "<no read access>");
     649              :          else {
     650              :             if (flags & 0x8)
     651              :                db_sprintfh(data_str, buf, key.item_size, 0, key.type);
     652              :             else
     653              :                db_sprintf(data_str, buf, key.item_size, 0, key.type);
     654              :          }
     655              : 
     656              :          if (flags & 0x1) {
     657              :             sprintf(line + 32, "%s", rpc_tid_name(key.type));
     658              :             line[strlen(line)] = ' ';
     659              :             sprintf(line + 40, "%d", key.num_values);
     660              :             line[strlen(line)] = ' ';
     661              :             sprintf(line + 46, "%d", key.item_size);
     662              :             line[strlen(line)] = ' ';
     663              : 
     664              :             db_get_key_time(hDB, hKey, &delta);
     665              :             if (delta < 60)
     666              :                sprintf(line + 52, "%ds", delta);
     667              :             else if (delta < 3600)
     668              :                sprintf(line + 52, "%1.0lfm", delta / 60.0);
     669              :             else if (delta < 86400)
     670              :                sprintf(line + 52, "%1.0lfh", delta / 3600.0);
     671              :             else if (delta < 86400 * 99)
     672              :                sprintf(line + 52, "%1.0lfh", delta / 86400.0);
     673              :             else
     674              :                sprintf(line + 52, ">99d");
     675              :             line[strlen(line)] = ' ';
     676              : 
     677              :             sprintf(line + 57, "%d", key.notify_count);
     678              :             line[strlen(line)] = ' ';
     679              : 
     680              :             if (key.access_mode & MODE_READ)
     681              :                line[61] = 'R';
     682              :             if (key.access_mode & MODE_WRITE)
     683              :                line[62] = 'W';
     684              :             if (key.access_mode & MODE_DELETE)
     685              :                line[63] = 'D';
     686              :             if (key.access_mode & MODE_EXCLUSIVE)
     687              :                line[64] = 'E';
     688              : 
     689              :             if (key.num_values == 1)
     690              :                strcpy(line + 66, data_str);
     691              :             else
     692              :                line[66] = 0;
     693              :          } else if (key.num_values == 1)
     694              :             strcpy(line + 32, data_str);
     695              :          else
     696              :             line[32] = 0;
     697              : 
     698              :          printf("%s\n", line);
     699              : 
     700              :          if (key.num_values > 1) {
     701              :             for (j = 0; j < key.num_values; j++) {
     702              :                std::string data_str;
     703              :                
     704              :                if (flags & 0x8)
     705              :                   data_str = db_sprintfh(buf, key.item_size, j, key.type);
     706              :                else
     707              :                   data_str = db_sprintf(buf, key.item_size, j, key.type);
     708              : 
     709              :                memset(line, ' ', 80);
     710              :                line[80] = 0;
     711              : 
     712              :                if (flags & 0x1) {
     713              :                   sprintf(line + 40, "[%d]", j);
     714              :                   line[strlen(line)] = ' ';
     715              : 
     716              :                   strcpy(line + 56, data_str);
     717              :                } else
     718              :                   strcpy(line + 32, data_str);
     719              : 
     720              :                printf("%s\n", line);
     721              :             }
     722              :          }
     723              : 
     724              :          free(buf);
     725              :       }
     726              :    }
     727              : 
     728              :    /* recurse subtree */
     729              :    if (key.type == TID_KEY && (flags & 0x2)) {
     730              :       for (i = 0;; i++) {
     731              :          db_enum_link(hDB, hKey, i, &hSubkey);
     732              : 
     733              :          if (!hSubkey)
     734              :             break;
     735              : 
     736              :          scan_tree(hDB, hSubkey, total_size_key, total_size_data, level + 1, flags);
     737              : 
     738              :          if (cm_is_ctrlc_pressed()) {
     739              :             if (level == 0)
     740              :                cm_ack_ctrlc_pressed();
     741              :             return;
     742              :          }
     743              :       }
     744              :    }
     745              : }
     746              : #endif
     747              : 
     748              : /*------------------------------------------------------------------*/
     749              : 
     750              : /* complete partial key name, gets called from cmd_edit */
     751            0 : INT cmd_dir(char *line, INT *cursor) {
     752              :    KEY key;
     753              :    HNDLE hDB, hKey, hSubkey;
     754              :    INT i, j, match, size;
     755              :    char *pc, partial[256], last_match[256];
     756              :    char head[256], tail[256], key_name[256], c;
     757              :    char test_key[256];
     758              :    BOOL blanks, mismatch;
     759              : 
     760            0 :    cm_get_experiment_database(&hDB, NULL);
     761              : 
     762              :    /* remember tail for later */
     763            0 :    strcpy(head, line);
     764            0 :    strcpy(tail, line + *cursor);
     765            0 :    line[*cursor] = 0;
     766              : 
     767              :    /* search beginning of key */
     768            0 :    pc = head;
     769              :    do {
     770            0 :       while (*pc && *pc != ' ')
     771            0 :          pc++;
     772            0 :       while (*pc && *pc == ' ')
     773            0 :          pc++;
     774            0 :    } while (*pc == '-'); /* skip flags */
     775              : 
     776            0 :    if (*pc) {
     777            0 :       strcpy(key_name, pc);
     778            0 :       *pc = 0; /* end of head */
     779              :    } else
     780            0 :       key_name[0] = 0;
     781              : 
     782              :    /* check if key exists (for "set <key>" completion) */
     783            0 :    if (strncmp(head, "set", 3) == 0 && strlen(key_name) > 0) {
     784            0 :       std::string ystr;
     785            0 :       if (key_name[0] == '"')
     786            0 :          ystr = (key_name + 1);
     787              :       else
     788            0 :          ystr = key_name;
     789            0 :       if (key_name[0] != '/') {
     790            0 :          strcpy(test_key, pwd);
     791            0 :          if (test_key[strlen(test_key) - 1] != '/')
     792            0 :             strcat(test_key, "/");
     793            0 :          strcat(test_key, ystr.c_str());// FIXME: buffer overflow. KO aug2024
     794              :       } else {
     795            0 :          strcpy(test_key, ystr.c_str());// FIXME: buffer overflow. KO aug2024
     796              :       }
     797              : 
     798            0 :       pc = test_key + strlen(test_key) - 1;
     799            0 :       while (pc > test_key && (*pc == ' ' || *pc == '"'))
     800            0 :          *pc-- = 0;
     801            0 :       int status = db_find_key(hDB, 0, test_key, &hSubkey);
     802            0 :       if (status == DB_SUCCESS) {
     803              :          /* retrieve key data */
     804            0 :          db_get_link(hDB, hSubkey, &key);
     805              : 
     806            0 :          if (key.type != TID_KEY) {
     807            0 :             if (strlen(key_name) > 0 && key_name[strlen(key_name) - 1] != ' ')
     808            0 :                strcat(key_name, " ");
     809              : 
     810            0 :             assert(key.total_size > 0);
     811            0 :             char *buf = (char *) malloc(key.total_size);
     812            0 :             size = key.total_size;
     813            0 :             status = db_get_link_data(hDB, hSubkey, buf, &size, key.type);
     814              : 
     815            0 :             std::string xstr;
     816              : 
     817            0 :             if (key.type == TID_STRING || key.type == TID_LINK) {
     818            0 :                xstr += "\"";
     819            0 :                xstr += buf;
     820            0 :                xstr += "\"";
     821              :             } else {
     822            0 :                xstr = db_sprintf(buf, size, 0, key.type);
     823              :             }
     824              : 
     825            0 :             free(buf);
     826              : 
     827            0 :             strcpy(line, head);
     828            0 :             strcat(line, key_name);
     829            0 :             strcat(line, xstr.c_str());// FIXME: buffer overflow. KO Aug2024
     830            0 :             *cursor = strlen(line);
     831            0 :             strcat(line, tail);
     832            0 :             return TRUE;
     833            0 :          }
     834              :       }
     835            0 :    }
     836              : 
     837              :    /* combine pwd and key_name */
     838            0 :    pc = key_name;
     839            0 :    if (*pc == '"')
     840            0 :       pc++;
     841              : 
     842              :    char str[256];// FIXME: buffer overflows. K.O> Aug2024
     843            0 :    str[0] = 0;
     844              : 
     845            0 :    if (*pc != '/') {
     846            0 :       strcpy(str, pwd);
     847            0 :       if (str[strlen(str) - 1] != '/')
     848            0 :          strcat(str, "/");
     849            0 :       strcat(str, pc);
     850              :    } else
     851            0 :       strcpy(str, pc);
     852              : 
     853              :    /* split key_name into known and new directory */
     854            0 :    for (pc = str + strlen(str) - 1; pc > str && *pc != '/'; pc--)
     855              :       ;
     856              : 
     857            0 :    if (*pc == '/') {
     858            0 :       *pc = 0;
     859            0 :       strcpy(partial, pc + 1);
     860              :    } else
     861            0 :       strcpy(partial, str);
     862              : 
     863            0 :    db_find_link(hDB, 0, str, &hKey);
     864            0 :    for (i = 0, match = 0;; i++) {
     865            0 :       db_enum_link(hDB, hKey, i, &hSubkey);
     866              : 
     867            0 :       if (!hSubkey)
     868            0 :          break;
     869              : 
     870            0 :       db_get_link(hDB, hSubkey, &key);
     871            0 :       strcpy(str, key.name);
     872              : 
     873            0 :       str[strlen(partial)] = 0;
     874              : 
     875            0 :       if (equal_ustring(str, partial))
     876            0 :          match++;
     877              :    }
     878              : 
     879            0 :    if (match != 1)
     880            0 :       printf("\r\n");
     881              : 
     882            0 :    for (i = 0;; i++) {
     883            0 :       db_enum_link(hDB, hKey, i, &hSubkey);
     884              : 
     885            0 :       if (!hSubkey)
     886            0 :          break;
     887              : 
     888            0 :       db_get_link(hDB, hSubkey, &key);
     889            0 :       strcpy(str, key.name);
     890              : 
     891            0 :       str[strlen(partial)] = 0;
     892              : 
     893            0 :       if (equal_ustring(str, partial)) {
     894            0 :          if (match == 1) {
     895              :             /* search split point */
     896            0 :             pc = key_name;
     897            0 :             if (strlen(key_name) > 0)
     898            0 :                for (pc = key_name + strlen(key_name) - 1; pc > key_name && *pc != '/';
     899              :                     pc--)
     900              :                   ;
     901            0 :             if (*pc == '/')
     902            0 :                pc++;
     903              : 
     904            0 :             strcpy(pc, key.name);
     905            0 :             if (key.type == TID_KEY)
     906            0 :                strcat(pc, "/");
     907              : 
     908              :             /* insert '"' if blanks in name */
     909            0 :             if (strchr(key.name, ' ')) {
     910            0 :                if (key_name[0] != '"') {
     911            0 :                   for (i = strlen(key_name); i >= 0; i--)
     912            0 :                      key_name[i + 1] = key_name[i];
     913              : 
     914            0 :                   key_name[0] = '"';
     915              :                }
     916            0 :                if (key.type != TID_KEY)
     917            0 :                   strcat(key_name, "\"");
     918              :             }
     919              : 
     920            0 :             if (key.type != TID_KEY) {
     921            0 :                if (key_name[0] == '"' && key_name[strlen(key_name) - 1] != '"')
     922            0 :                   strcat(pc, "\" ");
     923              :                else
     924            0 :                   strcat(pc, " ");
     925              :             }
     926              : 
     927            0 :             strcpy(line, head);
     928            0 :             strcat(line, key_name);
     929            0 :             *cursor = strlen(line);
     930            0 :             strcat(line, tail);
     931            0 :             return TRUE;
     932              :          }
     933              :       }
     934            0 :       if (match == 0 || (match > 1 && equal_ustring(str, partial)))
     935            0 :          printf("%s\r\n", key.name);
     936              :    }
     937              : 
     938            0 :    if (match > 1 && key_name[0]) {
     939            0 :       blanks = FALSE;
     940              : 
     941            0 :       for (j = strlen(partial);; j++) {
     942            0 :          for (i = 0, c = 1, mismatch = FALSE;; i++) {
     943            0 :             db_enum_link(hDB, hKey, i, &hSubkey);
     944              : 
     945            0 :             if (!hSubkey)
     946            0 :                break;
     947              : 
     948            0 :             db_get_link(hDB, hSubkey, &key);
     949            0 :             strcpy(str, key.name);
     950              : 
     951            0 :             str[strlen(partial)] = 0;
     952              : 
     953            0 :             if (strchr(key.name, ' '))
     954            0 :                blanks = TRUE;
     955              : 
     956            0 :             if (equal_ustring(str, partial)) {
     957            0 :                strcpy(last_match, key.name);
     958            0 :                if (c == 1)
     959            0 :                   c = toupper(key.name[j]);
     960            0 :                else if (c != toupper(key.name[j])) {
     961            0 :                   mismatch = TRUE;
     962            0 :                   break;
     963              :                }
     964              :             }
     965              :          }
     966              : 
     967            0 :          if (mismatch || last_match[j] == 0)
     968              :             break;
     969              :       }
     970              : 
     971              :       /* search split point */
     972            0 :       for (pc = key_name + strlen(key_name) - 1; pc > key_name && *pc != '/'; pc--)
     973              :          ;
     974            0 :       if (*pc == '/')
     975            0 :          pc++;
     976              : 
     977            0 :       for (i = 0; i < j; i++)
     978            0 :          pc[i] = last_match[i];
     979            0 :       pc[i] = 0;
     980              : 
     981              :       /* insert '"' if blanks in name */
     982            0 :       if (blanks) {
     983            0 :          if (key_name[0] != '"') {
     984            0 :             for (i = strlen(key_name); i >= 0; i--)
     985            0 :                key_name[i + 1] = key_name[i];
     986              : 
     987            0 :             key_name[0] = '"';
     988              :          }
     989              :       }
     990              : 
     991            0 :       strcpy(line, head);
     992            0 :       strcat(line, key_name);
     993            0 :       *cursor = strlen(line);
     994            0 :       strcat(line, tail);
     995            0 :       return TRUE;
     996              :    }
     997              : 
     998              :    /* beep if not found */
     999            0 :    printf("\007");
    1000              : 
    1001            0 :    strcpy(line, head);
    1002            0 :    strcat(line, key_name);
    1003            0 :    *cursor = strlen(line);
    1004            0 :    strcat(line, tail);
    1005            0 :    return FALSE;
    1006              : }
    1007              : 
    1008              : /*------------------------------------------------------------------*/
    1009              : 
    1010            0 : INT search_key(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *info) {
    1011            0 :    char *pattern = (char *) info;
    1012              : 
    1013            0 :    if (match(pattern, key->name)) {
    1014            0 :       std::string path = db_get_path(hDB, hKey);
    1015            0 :       std::string line = path + " : ";
    1016              : 
    1017            0 :       if (key->type != TID_KEY) {
    1018            0 :          assert(key->total_size > 0);
    1019            0 :          char *data = (char *) malloc(key->total_size);
    1020            0 :          int size = key->total_size;
    1021            0 :          int status = db_get_data(hDB, hKey, data, &size, key->type);
    1022              : 
    1023            0 :          std::string data_str;
    1024              : 
    1025            0 :          if (status == DB_NO_ACCESS)
    1026            0 :             data_str = "<no read access>";
    1027              :          else
    1028            0 :             data_str = db_sprintf(data, key->item_size, 0, key->type);
    1029              : 
    1030            0 :          if (key->num_values == 1)
    1031            0 :             line += data_str;
    1032              : 
    1033            0 :          printf("%s\n", line.c_str());
    1034              : 
    1035            0 :          if (key->num_values > 1)
    1036            0 :             for (int i = 0; i < key->num_values; i++) {
    1037            0 :                data_str = db_sprintf(data, key->item_size, i, key->type);
    1038              : 
    1039            0 :                printf("  [%d] : %s\n", i, data_str.c_str());
    1040              :             }
    1041            0 :          free(data);
    1042            0 :       } else {
    1043            0 :          printf("%s\n", line.c_str());
    1044              :       }
    1045            0 :    }
    1046              : 
    1047            0 :    return SUCCESS;
    1048              : }
    1049              : 
    1050              : /*------------------------------------------------------------------*/
    1051              : 
    1052            0 : void del_tree(HNDLE hDB, HNDLE hKey, INT level) {
    1053              :    INT i;
    1054              :    KEY key;
    1055              :    HNDLE hSubkey;
    1056              : 
    1057            0 :    for (i = 0;; i++) {
    1058            0 :       db_enum_link(hDB, hKey, i, &hSubkey);
    1059              : 
    1060            0 :       if (!hSubkey)
    1061            0 :          break;
    1062              : 
    1063            0 :       db_get_key(hDB, hSubkey, &key);
    1064            0 :       if (key.type == TID_KEY)
    1065            0 :          del_tree(hDB, hSubkey, level + 1);
    1066              : 
    1067            0 :       if (rand() < RAND_MAX / 10)
    1068            0 :          db_delete_key(hDB, hSubkey, 0);
    1069              :    }
    1070            0 : }
    1071              : 
    1072              : /*------------------------------------------------------------------*/
    1073              : 
    1074            0 : static void xwrite(const char *filename, int fd, const void *data, int size) {
    1075            0 :    int wr = write(fd, data, size);
    1076            0 :    if (wr != size) {
    1077            0 :       cm_msg(MERROR, "xwrite", "cannot write to \'%s\', write(%d) returned %d, errno %d (%s)", filename, size, wr, errno, strerror(errno));
    1078              :    }
    1079            0 : }
    1080              : 
    1081            0 : void create_experim_h(HNDLE hDB, const char *analyzer_name) {
    1082              :    INT i, index, subindex, hfile, status, size;
    1083              :    HNDLE hKey, hKeyRoot, hKeyEq, hDefKey, hKeyBank, hKeyPar;
    1084              :    char str[100 + 80], eq_name[80], subeq_name[80];
    1085              :    KEY key;
    1086              :    time_t now;
    1087              : 
    1088            0 :    char experim_h_comment1[] =
    1089              :       "/********************************************************************\\\n\
    1090              : \n\
    1091              :   Name:         experim.h\n\
    1092              :   Created by:   ODBedit program\n\
    1093              : \n\
    1094              :   Contents:     This file contains C structures for the \"Experiment\"\n\
    1095              :                 tree in the ODB and the \"/Analyzer/Parameters\" tree.\n\
    1096              : \n\
    1097              :                 Additionally, it contains the \"Settings\" subtree for\n\
    1098              :                 all items listed under \"/Equipment\" as well as their\n\
    1099              :                 event definition.\n\
    1100              : \n\
    1101              :                 It can be used by the frontend and analyzer to work\n\
    1102              :                 with these information.\n\
    1103              : \n\
    1104              :                 All C structures are accompanied with a string represen-\n\
    1105              :                 tation which can be used in the db_create_record function\n\
    1106              :                 to setup an ODB structure which matches the C structure.\n\
    1107              : \n";
    1108            0 :    char experim_h_comment2[] =
    1109              :       "\\********************************************************************/\n\n";
    1110              : 
    1111            0 :    const char *file_name = "experim.h";
    1112              : 
    1113              :    /* create file */
    1114            0 :    hfile = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    1115            0 :    if (hfile == -1)
    1116            0 :       cm_msg(MERROR, "create_experim_h", "cannot open experim.h file.");
    1117              : 
    1118              :    /* write comment to file */
    1119            0 :    xwrite(file_name, hfile, experim_h_comment1, strlen(experim_h_comment1));
    1120            0 :    time(&now);
    1121              :    char ctimebuf[32];
    1122            0 :    ctime_r(&now, ctimebuf);
    1123            0 :    sprintf(str, "  Created on:   %s\n", ctimebuf);
    1124            0 :    xwrite(file_name, hfile, str, strlen(str));
    1125            0 :    xwrite(file_name, hfile, experim_h_comment2, strlen(experim_h_comment2));
    1126              : 
    1127              :    /* write /experiment/run parameters */
    1128            0 :    db_find_key(hDB, 0, "/Experiment/Run Parameters", &hKey);
    1129            0 :    if (hKey) {
    1130            0 :       sprintf(str, "#define EXP_PARAM_DEFINED\n\n");
    1131            0 :       xwrite(file_name, hfile, str, strlen(str));
    1132            0 :       db_save_struct(hDB, hKey, file_name, "EXP_PARAM", TRUE);
    1133            0 :       db_save_string(hDB, hKey, file_name, "EXP_PARAM_STR", TRUE);
    1134            0 :       lseek(hfile, 0, SEEK_END);
    1135              :    }
    1136              : 
    1137              :    /* write /experiment/edit on start */
    1138            0 :    db_find_key(hDB, 0, "/Experiment/Edit on start", &hKey);
    1139            0 :    if (hKey) {
    1140            0 :       sprintf(str, "#define EXP_EDIT_DEFINED\n\n");
    1141            0 :       xwrite(file_name, hfile, str, strlen(str));
    1142            0 :       db_save_struct(hDB, hKey, file_name, "EXP_EDIT", TRUE);
    1143            0 :       db_save_string(hDB, hKey, file_name, "EXP_EDIT_STR", TRUE);
    1144            0 :       lseek(hfile, 0, SEEK_END);
    1145              :    }
    1146              : 
    1147              :    /* write /<Analyzer>/parameters tree */
    1148            0 :    sprintf(str, "/%s/Parameters", analyzer_name);
    1149            0 :    status = db_find_key(hDB, 0, str, &hKeyRoot);
    1150            0 :    if (status != DB_SUCCESS) {
    1151            0 :       printf("Analyzer \"%s\" not found in ODB, skipping analyzer parameters.\n",
    1152              :              analyzer_name);
    1153              :    } else {
    1154            0 :       for (index = 0;; index++) {
    1155            0 :          status = db_enum_key(hDB, hKeyRoot, index, &hKeyPar);
    1156            0 :          if (status == DB_NO_MORE_SUBKEYS)
    1157            0 :             break;
    1158              : 
    1159            0 :          db_get_key(hDB, hKeyPar, &key);
    1160            0 :          mstrlcpy(eq_name, key.name, sizeof(eq_name));
    1161            0 :          name2c(eq_name);
    1162            0 :          for (i = 0; i < (int) strlen(eq_name); i++)
    1163            0 :             eq_name[i] = toupper(eq_name[i]);
    1164              : 
    1165            0 :          lseek(hfile, 0, SEEK_END);
    1166            0 :          sprintf(str, "#ifndef EXCL_%s\n\n", eq_name);
    1167            0 :          xwrite(file_name, hfile, str, strlen(str));
    1168              : 
    1169            0 :          sprintf(str, "#define %s_PARAM_DEFINED\n\n", eq_name);
    1170            0 :          xwrite(file_name, hfile, str, strlen(str));
    1171            0 :          sprintf(str, "%s_PARAM", eq_name);
    1172            0 :          db_save_struct(hDB, hKeyPar, file_name, str, TRUE);
    1173            0 :          sprintf(str, "%s_PARAM_STR", eq_name);
    1174            0 :          db_save_string(hDB, hKeyPar, file_name, str, TRUE);
    1175              : 
    1176            0 :          lseek(hfile, 0, SEEK_END);
    1177            0 :          sprintf(str, "#endif\n\n");
    1178            0 :          xwrite(file_name, hfile, str, strlen(str));
    1179              :       }
    1180              :    }
    1181              : 
    1182              :    /* loop through equipment list */
    1183            0 :    status = db_find_key(hDB, 0, "/Equipment", &hKeyRoot);
    1184            0 :    if (status == DB_SUCCESS)
    1185            0 :       for (index = 0;; index++) {
    1186            0 :          status = db_enum_key(hDB, hKeyRoot, index, &hKeyEq);
    1187            0 :          if (status == DB_NO_MORE_SUBKEYS)
    1188            0 :             break;
    1189              : 
    1190            0 :          db_get_key(hDB, hKeyEq, &key);
    1191            0 :          strcpy(eq_name, key.name);
    1192            0 :          name2c(eq_name);
    1193            0 :          for (i = 0; i < (int) strlen(eq_name); i++)
    1194            0 :             eq_name[i] = toupper(eq_name[i]);
    1195              : 
    1196            0 :          lseek(hfile, 0, SEEK_END);
    1197            0 :          sprintf(str, "#ifndef EXCL_%s\n\n", eq_name);
    1198            0 :          xwrite(file_name, hfile, str, strlen(str));
    1199              : 
    1200            0 :          size = sizeof(str);
    1201            0 :          str[0] = 0;
    1202            0 :          db_get_value(hDB, hKeyEq, "Common/Format", str, &size, TID_STRING, TRUE);
    1203              : 
    1204              :          /* if event is in fixed format, extract header file */
    1205            0 :          if (equal_ustring(str, "Fixed")) {
    1206            0 :             db_find_key(hDB, hKeyEq, "Variables", &hDefKey);
    1207            0 :             if (hDefKey) {
    1208            0 :                lseek(hfile, 0, SEEK_END);
    1209            0 :                sprintf(str, "#define %s_EVENT_DEFINED\n\n", eq_name);
    1210            0 :                xwrite(file_name, hfile, str, strlen(str));
    1211              : 
    1212            0 :                sprintf(str, "%s_EVENT", eq_name);
    1213            0 :                db_save_struct(hDB, hDefKey, file_name, str, TRUE);
    1214            0 :                sprintf(str, "%s_EVENT_STR", eq_name);
    1215            0 :                db_save_string(hDB, hDefKey, file_name, str, TRUE);
    1216              :             }
    1217              :          }
    1218              : 
    1219              :          /* if event is in MIDAS format, extract bank definition */
    1220            0 :          else if (equal_ustring(str, "MIDAS")) {
    1221            0 :             db_find_key(hDB, hKeyEq, "Variables", &hDefKey);
    1222            0 :             if (hDefKey) {
    1223            0 :                for (i = 0;; i++) {
    1224            0 :                   status = db_enum_key(hDB, hDefKey, i, &hKeyBank);
    1225            0 :                   if (status == DB_NO_MORE_SUBKEYS)
    1226            0 :                      break;
    1227              : 
    1228            0 :                   db_get_key(hDB, hKeyBank, &key);
    1229              : 
    1230            0 :                   if (key.type == TID_KEY) {
    1231            0 :                      lseek(hfile, 0, SEEK_END);
    1232            0 :                      sprintf(str, "#define %s_BANK_DEFINED\n\n", key.name);
    1233            0 :                      xwrite(file_name, hfile, str, strlen(str));
    1234              : 
    1235            0 :                      sprintf(str, "%s_BANK", key.name);
    1236            0 :                      db_save_struct(hDB, hKeyBank, file_name, str, TRUE);
    1237            0 :                      sprintf(str, "%s_BANK_STR", key.name);
    1238            0 :                      db_save_string(hDB, hKeyBank, file_name, str, TRUE);
    1239              :                   }
    1240              :                }
    1241              :             }
    1242              :          }
    1243              : 
    1244              :          /* Scan sub tree for that equipment */
    1245            0 :          for (subindex = 0;; subindex++) {
    1246            0 :             status = db_enum_key(hDB, hKeyEq, subindex, &hDefKey);
    1247            0 :             if (status == DB_NO_MORE_SUBKEYS)
    1248            0 :                break;
    1249              : 
    1250            0 :             db_get_key(hDB, hDefKey, &key);
    1251            0 :             strcpy(subeq_name, key.name);
    1252            0 :             name2c(subeq_name);
    1253              : 
    1254            0 :             for (i = 0; i < (int) strlen(subeq_name); i++)
    1255            0 :                subeq_name[i] = toupper(subeq_name[i]);
    1256              : 
    1257              :             /* Skip only the statistics */
    1258            0 :             if (!equal_ustring(subeq_name, "statistics") && !equal_ustring(subeq_name, "variables")) {
    1259            0 :                lseek(hfile, 0, SEEK_END);
    1260            0 :                sprintf(str, "#define %s_%s_DEFINED\n\n", eq_name, subeq_name);
    1261            0 :                xwrite(file_name, hfile, str, strlen(str));
    1262              : 
    1263            0 :                sprintf(str, "%s_%s", eq_name, subeq_name);
    1264            0 :                db_save_struct(hDB, hDefKey, file_name, str, TRUE);
    1265            0 :                sprintf(str, "%s_%s_STR", eq_name, subeq_name);
    1266            0 :                db_save_string(hDB, hDefKey, file_name, str, TRUE);
    1267              :             }
    1268              :          }
    1269              : 
    1270            0 :          lseek(hfile, 0, SEEK_END);
    1271            0 :          sprintf(str, "#endif\n\n");
    1272            0 :          xwrite(file_name, hfile, str, strlen(str));
    1273              :       }
    1274              : 
    1275            0 :    close(hfile);
    1276              : 
    1277            0 :    std::string cwd = ss_getcwd();
    1278            0 :    printf("\"experim.h\" has been written to %s/%s\n", cwd.c_str(), file_name);
    1279            0 : }
    1280              : 
    1281              : /*------------------------------------------------------------------*/
    1282              : 
    1283            0 : INT cmd_idle() {
    1284              :    INT status;
    1285              : 
    1286            0 :    need_redraw = FALSE;
    1287              : 
    1288            0 :    status = cm_yield(100);
    1289              : 
    1290              :    /* abort if server connection is broken */
    1291            0 :    if (status == SS_ABORT || status == RPC_SHUTDOWN) {
    1292            0 :       if (status == SS_ABORT)
    1293            0 :          printf("Server connection broken.\n");
    1294              : 
    1295            0 :       ss_getchar(1);
    1296            0 :       cm_disconnect_experiment();
    1297            0 :       exit(0);
    1298              :    }
    1299              : 
    1300              :    /* check for broken client connections */
    1301            0 :    rpc_client_check();
    1302              : 
    1303            0 :    return need_redraw;
    1304              : }
    1305              : 
    1306              : /*------------------------------------------------------------------*/
    1307              : 
    1308            0 : void compose_name(char *pwd, char *name, char *full_name) {
    1309            0 :    if (name[0] != '/') {
    1310            0 :       strcpy(full_name, pwd);
    1311            0 :       if (full_name[strlen(full_name) - 1] != '/')
    1312            0 :          strcat(full_name, "/");
    1313            0 :       strcat(full_name, name);
    1314              :    } else
    1315            0 :       strcpy(full_name, name);
    1316            0 : }
    1317              : 
    1318              : /*------------------------------------------------------------------*/
    1319              : 
    1320            0 : void assemble_prompt(char *prompt, int psize, char *host_name, char *exp_name, char *pwd) {
    1321              :    HNDLE hDB;
    1322              :    char mask[256], str[32];
    1323              :    int state, size;
    1324              :    char *pp, *pm, *pc;
    1325              :    time_t now;
    1326              : 
    1327            0 :    const char *state_char[] = {"U", "S", "P", "R"};
    1328            0 :    const char *state_str[] = {"Unknown", "Stopped", "Paused", "Running"};
    1329              : 
    1330            0 :    cm_get_experiment_database(&hDB, NULL);
    1331              : 
    1332            0 :    size = sizeof(mask);
    1333            0 :    strcpy(mask, "[%h:%e:%s]%p>");
    1334            0 :    db_get_value(hDB, 0, "/System/Prompt", mask, &size, TID_STRING, TRUE);
    1335              : 
    1336            0 :    state = STATE_STOPPED;
    1337            0 :    size = sizeof(state);
    1338            0 :    db_get_value(hDB, 0, "/Runinfo/State", &state, &size, TID_INT, TRUE);
    1339            0 :    if (state > STATE_RUNNING)
    1340            0 :       state = 0;
    1341              : 
    1342            0 :    pm = mask;
    1343            0 :    pp = prompt;
    1344            0 :    memset(prompt, 0, psize);
    1345              :    do {
    1346            0 :       if (*pm != '%') {
    1347            0 :          *pp++ = *pm++;
    1348              :       } else {
    1349            0 :          switch (*++pm) {
    1350            0 :             case 't':
    1351            0 :                time(&now);
    1352              :                assert(sizeof(str) >= 32);
    1353            0 :                ctime_r(&now, str);
    1354            0 :                str[19] = 0;
    1355            0 :                strcpy(pp, str + 11);
    1356            0 :                break;
    1357            0 :             case 'h':
    1358            0 :                if (host_name[0])
    1359            0 :                   strcat(pp, host_name);
    1360              :                else
    1361            0 :                   strcat(pp, "local");
    1362            0 :                break;
    1363            0 :             case 'e':
    1364            0 :                if (exp_name[0])
    1365            0 :                   strcat(pp, exp_name);
    1366              :                else
    1367            0 :                   strcat(pp, "Default");
    1368            0 :                break;
    1369            0 :             case 's':
    1370            0 :                strcat(pp, state_char[state]);
    1371            0 :                break;
    1372            0 :             case 'S':
    1373            0 :                strcat(pp, state_str[state]);
    1374            0 :                break;
    1375            0 :             case 'P':
    1376            0 :                strcat(pp, pwd);
    1377            0 :                break;
    1378            0 :             case 'p':
    1379            0 :                pc = pwd + strlen(pwd) - 1;
    1380            0 :                while (*pc != '/' && pc != pwd)
    1381            0 :                   pc--;
    1382            0 :                if (pc == pwd)
    1383            0 :                   strcat(pp, pwd);
    1384              :                else
    1385            0 :                   strcat(pp, pc + 1);
    1386            0 :                break;
    1387              :          }
    1388            0 :          pm++;
    1389            0 :          pp += strlen(pp);
    1390              :       }
    1391            0 :    } while (*pm);
    1392            0 : }
    1393              : 
    1394              : /*------------------------------------------------------------------*/
    1395              : 
    1396            0 : void watch_callback(HNDLE hDB, HNDLE hKey, INT index, void *info) {
    1397              :    KEY key;
    1398              :    int status;
    1399              : 
    1400            0 :    std::string path = db_get_path(hDB, hKey);
    1401              : 
    1402            0 :    status = db_get_key(hDB, hKey, &key);
    1403            0 :    if (status != DB_SUCCESS) {
    1404            0 :       printf("callback for invalid or deleted hkey %d odb path %s\n", hKey, path.c_str());
    1405            0 :       return;
    1406              :    }
    1407              : 
    1408            0 :    if (key.type == TID_KEY)
    1409            0 :       printf("%s modified\n", path.c_str());
    1410              :    else {
    1411            0 :       if (key.num_values == 1) {
    1412            0 :          if (key.type == TID_STRING) {
    1413            0 :             std::string data;
    1414            0 :             db_get_value_string(hDB, 0, path.c_str(), 0, &data);
    1415            0 :             printf("%s = \"%s\"\n", path.c_str(), data.c_str());
    1416            0 :          } else {
    1417              :             char data[10000];
    1418            0 :             int size = sizeof(data);
    1419            0 :             db_get_data(hDB, hKey, data, &size, key.type);
    1420            0 :             std::string str = db_sprintf(data, size, 0, key.type);
    1421            0 :             printf("%s = %s\n", path.c_str(), str.c_str());
    1422            0 :          }
    1423              :       } else {
    1424            0 :          if (index == -1) {
    1425            0 :             printf("%s[*] modified\n", path.c_str());
    1426              :          } else {
    1427            0 :             if (key.type == TID_STRING) {
    1428            0 :                std::string data;
    1429            0 :                db_get_value_string(hDB, 0, path.c_str(), index, &data);
    1430            0 :                printf("%s[%d] = \"%s\"\n", path.c_str(), index, data.c_str());
    1431            0 :             } else {
    1432              :                char data[10000];
    1433            0 :                int size = sizeof(data);
    1434            0 :                db_get_data_index(hDB, hKey, data, &size, index, key.type);
    1435            0 :                std::string str = db_sprintf(data, size, 0, key.type);
    1436            0 :                printf("%s[%d] = %s\n", path.c_str(), index, str.c_str());
    1437            0 :             }
    1438              :          }
    1439              :       }
    1440              :    }
    1441            0 : }
    1442              : 
    1443              : /*------------------------------------------------------------------*/
    1444              : 
    1445            0 : int command_loop(char *host_name, char *exp_name, char *cmd, char *start_dir) {
    1446            0 :    INT status = 0, i, k, state, size, old_run_number, new_run_number;
    1447              :    char line[2000], prompt[256];
    1448              :    char param[10][2000];
    1449              :    char str[2000], str2[80], name[256], *pc;
    1450              :    char old_password[32], new_password[32];
    1451              :    INT nparam, flags, index1, index2, debug_flag, mthread_flag;
    1452              :    WORD mode;
    1453              :    HNDLE hDB, hKey, hKeyClient, hSubkey, hRootKey;
    1454              :    KEY key;
    1455            0 :    char user_name[80] = "";
    1456            0 :    FILE *cmd_file = NULL;
    1457            0 :    DWORD last_msg_time = 0;
    1458              :    char message[2000], client_name[256], *p;
    1459              :    INT n1, n2;
    1460              :    PRINT_INFO print_info;
    1461              : 
    1462            0 :    cm_get_experiment_database(&hDB, &hKeyClient);
    1463              : 
    1464              :    /* command loop */
    1465            0 :    if (start_dir[0])
    1466            0 :       strcpy(pwd, start_dir);
    1467              :    else
    1468            0 :       strcpy(pwd, "/");
    1469              : 
    1470              :    /* check if dir exists */
    1471            0 :    if (db_find_key(hDB, 0, pwd, &hKey) != DB_SUCCESS) {
    1472            0 :       printf("Directory \"%s\" not found.\n", pwd);
    1473            0 :       return -1;
    1474              :    }
    1475              : 
    1476              :    /* open command file */
    1477            0 :    if (cmd[0] == '@') {
    1478            0 :       cmd_file = fopen(cmd + 1, "r");
    1479            0 :       if (cmd_file == NULL) {
    1480            0 :          printf("Command file %s not found.\n", cmd + 1);
    1481            0 :          return -1;
    1482              :       }
    1483              :    }
    1484              : 
    1485              :    do {
    1486              :       /* print prompt */
    1487            0 :       if (!cmd_mode) {
    1488            0 :          assemble_prompt(prompt, sizeof(prompt), host_name, exp_name, pwd);
    1489              : 
    1490            0 :          in_cmd_edit = TRUE;
    1491            0 :          line[0] = 0;
    1492            0 :          cmd_edit(prompt, line, cmd_dir, cmd_idle);
    1493            0 :          in_cmd_edit = FALSE;
    1494            0 :       } else if (cmd[0] != '@')
    1495            0 :          mstrlcpy(line, cmd, sizeof(line));
    1496              :       else {
    1497            0 :          memset(line, 0, sizeof(line));
    1498            0 :          char *s = fgets(line, sizeof(line), cmd_file);
    1499              : 
    1500            0 :          if (s == NULL || line[0] == 0)
    1501              :             break;
    1502              : 
    1503              :          /* cut off CR */
    1504            0 :          while (strlen(line) > 0 && line[strlen(line) - 1] == '\n')
    1505            0 :             line[strlen(line) - 1] = 0;
    1506              : 
    1507            0 :          if (line[0] == 0)
    1508            0 :             continue;
    1509              :       }
    1510              : 
    1511              :       /* analyze line */
    1512            0 :       nparam = 0;
    1513            0 :       pc = line;
    1514            0 :       while (*pc == ' ')
    1515            0 :          pc++;
    1516              : 
    1517            0 :       memset(param, 0, sizeof(param));
    1518              :       do {
    1519            0 :          if (*pc == '"') {
    1520            0 :             pc++;
    1521            0 :             for (i = 0; *pc && *pc != '"' && i < (int) sizeof(param[0]) - 1; i++)
    1522            0 :                param[nparam][i] = *pc++;
    1523            0 :             if (*pc)
    1524            0 :                pc++;
    1525            0 :          } else if (*pc == '\'') {
    1526            0 :             pc++;
    1527            0 :             for (i = 0; *pc && *pc != '\'' && i < (int) sizeof(param[0]) - 1; i++)
    1528            0 :                param[nparam][i] = *pc++;
    1529            0 :             if (*pc)
    1530            0 :                pc++;
    1531            0 :          } else if (*pc == '`') {
    1532            0 :             pc++;
    1533            0 :             for (i = 0; *pc && *pc != '`' && i < (int) sizeof(param[0]) - 1; i++)
    1534            0 :                param[nparam][i] = *pc++;
    1535            0 :             if (*pc)
    1536            0 :                pc++;
    1537              :          } else
    1538            0 :             for (i = 0; *pc && *pc != ' ' && i < (int) sizeof(param[0]) - 1; i++)
    1539            0 :                param[nparam][i] = *pc++;
    1540            0 :          param[nparam][i] = 0;
    1541            0 :          while (*pc == ' ')
    1542            0 :             pc++;
    1543            0 :          nparam++;
    1544            0 :       } while (*pc);
    1545              : 
    1546              :       /* help */
    1547            0 :       if ((param[0][0] == 'h' && param[0][1] == 'e') || param[0][0] == '?')
    1548            0 :          print_help(param[1]);
    1549              : 
    1550              :       /* ls */
    1551            0 :       else if ((param[0][0] == 'l' && param[0][1] == 's') || (param[0][0] == 'd' && param[0][1] == 'i')) {
    1552            0 :          db_find_key(hDB, 0, pwd, &hKey);
    1553            0 :          print_info.flags = 0;
    1554            0 :          print_info.pattern[0] = 0;
    1555            0 :          ls_line = 0;
    1556            0 :          ls_abort = FALSE;
    1557              : 
    1558              :          /* parse options */
    1559            0 :          for (i = 1; i < 4; i++)
    1560            0 :             if (param[i][0] == '-') {
    1561            0 :                for (int j = 1; param[i][j] != ' ' && param[i][j]; j++) {
    1562            0 :                   if (param[i][j] == 'l')
    1563            0 :                      print_info.flags |= PI_LONG;
    1564            0 :                   if (param[i][j] == 'r')
    1565            0 :                      print_info.flags |= PI_RECURSIVE;
    1566            0 :                   if (param[i][j] == 'v')
    1567            0 :                      print_info.flags |= PI_VALUE;
    1568            0 :                   if (param[i][j] == 'h')
    1569            0 :                      print_info.flags |= PI_HEX;
    1570            0 :                   if (param[i][j] == 'p')
    1571            0 :                      print_info.flags |= PI_PAUSE;
    1572              :                }
    1573              :             }
    1574              : 
    1575            0 :          for (i = 1; param[i][0] == '-'; i++)
    1576              :             ;
    1577              : 
    1578              :          /* check if parameter contains array index */
    1579            0 :          print_info.index = -1;
    1580            0 :          if (strchr(param[i], '[') && strchr(param[i], ']')) {
    1581            0 :             for (p = strchr(param[i], '[') + 1; *p && *p != ']'; p++)
    1582            0 :                if (!isdigit(*p))
    1583            0 :                   break;
    1584              : 
    1585            0 :             if (*p && *p == ']') {
    1586            0 :                print_info.index = atoi(strchr(param[i], '[') + 1);
    1587            0 :                *strchr(param[i], '[') = 0;
    1588              :             }
    1589              :          }
    1590              : 
    1591            0 :          if (param[i][0]) {
    1592            0 :             if (strpbrk(param[i], "*?") != NULL) {
    1593              :                /* if parameter contains wildcards, set pattern */
    1594            0 :                strcpy(print_info.pattern, param[i]);
    1595              :             } else {
    1596            0 :                if (param[i][0] == '/')
    1597            0 :                   status = db_find_link(hDB, 0, param[i], &hKey);
    1598              :                else
    1599            0 :                   status = db_find_link(hDB, hKey, param[i], &hKey);
    1600              : 
    1601            0 :                if (status == DB_NO_KEY)
    1602            0 :                   printf("key %s not found\n", param[i]);
    1603              : 
    1604            0 :                if (status == DB_INVALID_LINK)
    1605            0 :                   printf("link %s points to invalid location\n", param[i]);
    1606              :             }
    1607              :          }
    1608              : 
    1609            0 :          if (hKey) {
    1610            0 :             if ((print_info.flags & PI_LONG) && (print_info.flags & PI_VALUE) == 0) {
    1611            0 :                printf("Key name                        Type    #Val  Size  Last Opn Mode Value\n");
    1612            0 :                printf("---------------------------------------------------------------------------\n");
    1613              :             }
    1614              : 
    1615            0 :             if (print_info.flags & PI_RECURSIVE) {
    1616            0 :                db_scan_tree(hDB, hKey, 0, print_key, &print_info);
    1617            0 :                if (cm_is_ctrlc_pressed())
    1618            0 :                   cm_ack_ctrlc_pressed();
    1619              :             } else {
    1620            0 :                db_get_link(hDB, hKey, &key);
    1621            0 :                if (key.type != TID_KEY)
    1622            0 :                   print_key(hDB, hKey, &key, 0, &print_info);
    1623              :                else
    1624            0 :                   for (i = 0;; i++) {
    1625            0 :                      if (cm_is_ctrlc_pressed()) {
    1626            0 :                         cm_ack_ctrlc_pressed();
    1627            0 :                         break;
    1628              :                      }
    1629              : 
    1630            0 :                      db_enum_link(hDB, hKey, i, &hSubkey);
    1631              : 
    1632            0 :                      if (!hSubkey)
    1633            0 :                         break;
    1634              : 
    1635            0 :                      db_get_link(hDB, hSubkey, &key);
    1636            0 :                      status = print_key(hDB, hSubkey, &key, 0, &print_info);
    1637            0 :                      if (status == 0)
    1638            0 :                         break;
    1639              :                   }
    1640              :             }
    1641              :          }
    1642            0 :       }
    1643              : 
    1644              :       /* cd */
    1645            0 :       else if (param[0][0] == 'c' && param[0][1] == 'd') {
    1646            0 :          if (strlen(param[1]) == 0)
    1647            0 :             strcpy(str, "/");
    1648              :          else
    1649            0 :             compose_name(pwd, param[1], str);
    1650              : 
    1651            0 :          status = db_find_key(hDB, 0, str, &hKey);
    1652              : 
    1653            0 :          if (strcmp(str, "/") == 0)
    1654            0 :             strcpy(pwd, str);
    1655            0 :          else if (status == DB_SUCCESS) {
    1656            0 :             db_get_key(hDB, hKey, &key);
    1657            0 :             if (key.type != TID_KEY)
    1658            0 :                printf("key has no subkeys\n");
    1659              :             else {
    1660            0 :                std::string path = db_get_path(hDB, hKey);
    1661            0 :                mstrlcpy(pwd, path.c_str(), sizeof(pwd));
    1662            0 :             }
    1663              :          } else
    1664            0 :             printf("key not found\n");
    1665            0 :       }
    1666              : 
    1667              :       /* pwd */
    1668            0 :       else if (param[0][0] == 'p' && param[0][1] == 'w') {
    1669            0 :          printf("%s\n", pwd);
    1670              :       }
    1671              : 
    1672              :       /* create */
    1673            0 :       else if (param[0][0] == 'c' && param[0][1] == 'r') {
    1674            0 :          compose_name(pwd, param[2], str);
    1675              : 
    1676              :          /* check if array */
    1677              : 
    1678            0 :          k = -1;
    1679            0 :          int j = 0;
    1680            0 :          if (str[strlen(str) - 1] == ']') {
    1681            0 :             if (strchr(str, '[')) {
    1682            0 :                j = atoi(strchr(str, '[') + 1);
    1683            0 :                mstrlcpy(str2, strchr(str, '[') + 1, sizeof(str2));
    1684            0 :                *strchr(str, '[') = 0;
    1685            0 :                if (strchr(str2, '['))
    1686            0 :                   k = atoi(strchr(str2, '[') + 1);
    1687              :             }
    1688              :          } else
    1689            0 :             j = 1;
    1690              : 
    1691              :          /* get TID */
    1692            0 :          for (i = 0; i < TID_LAST; i++) {
    1693            0 :             if (equal_ustring(rpc_tid_name(i), param[1]))
    1694            0 :                break;
    1695              :          }
    1696              : 
    1697            0 :          if (i == TID_LAST) {
    1698            0 :             printf("Unknown type. Must be one of:\n");
    1699            0 :             printf("{ UINT8,INT8,UINT16,INT16,UINT32,INT32,UINT64,INT64,BOOL,FLOAT,DOUBLE,STRING }\n");
    1700              :          } else {
    1701            0 :             db_create_key(hDB, 0, str, i);
    1702            0 :             db_find_key(hDB, 0, str, &hKey);
    1703            0 :             db_get_key(hDB, hKey, &key);
    1704              : 
    1705            0 :             if (i == TID_STRING) {
    1706            0 :                if (!cmd_mode && k == -1) {
    1707            0 :                   printf("String length [%d]: ", NAME_LENGTH);
    1708            0 :                   ss_gets(str, 256);
    1709            0 :                   if (str[0])
    1710            0 :                      key.item_size = atoi(str);
    1711              :                   else
    1712            0 :                      key.item_size = NAME_LENGTH;
    1713            0 :                } else if (k == -1)
    1714            0 :                   key.item_size = NAME_LENGTH;
    1715              :                else
    1716            0 :                   key.item_size = k;
    1717              : 
    1718            0 :                char *buf = (char *) malloc(key.item_size);
    1719            0 :                memset(buf, 0, sizeof(key.item_size));
    1720            0 :                db_set_link_data(hDB, hKey, buf, key.item_size, 1, key.type);
    1721            0 :                free(buf);
    1722              :             }
    1723              : 
    1724            0 :             if (j > 1) {
    1725            0 :                if (key.type == TID_LINK)
    1726            0 :                   key.item_size = NAME_LENGTH;
    1727            0 :                char *buf = (char *) malloc(key.item_size);
    1728            0 :                memset(buf, 0, sizeof(key.item_size));
    1729            0 :                db_set_link_data_index(hDB, hKey, buf, key.item_size, j - 1, key.type);
    1730            0 :                free(buf);
    1731              :             }
    1732              :          }
    1733            0 :       }
    1734              : 
    1735              :       /* mkdir */
    1736            0 :       else if (param[0][0] == 'm' && param[0][1] == 'k') {
    1737            0 :          compose_name(pwd, param[1], str);
    1738            0 :          db_create_key(hDB, 0, str, TID_KEY);
    1739              :       }
    1740              : 
    1741              :       /* link */
    1742            0 :       else if (param[0][0] == 'l' && param[0][1] == 'n') {
    1743            0 :          compose_name(pwd, param[2], str);
    1744            0 :          db_create_link(hDB, 0, str, param[1]);
    1745              :       }
    1746              : 
    1747              :       /* copy */
    1748            0 :       else if (param[0][0] == 'c' && (param[0][1] == 'o' || param[0][1] == 'p')) {
    1749              :          /* test if destination exists */
    1750            0 :          compose_name(pwd, param[2], str);
    1751            0 :          status = db_find_link(hDB, 0, str, &hKey);
    1752            0 :          if (status == DB_SUCCESS) {
    1753            0 :             if (cmd_mode)
    1754            0 :                str[0] = 'y';
    1755              :             else {
    1756            0 :                printf("Overwrite existing key\n\"%s\"\n(y/[n]) ", str);
    1757            0 :                ss_gets(str, 256);
    1758              :             }
    1759            0 :             if (str[0] == 'y')
    1760            0 :                db_delete_key(hDB, hKey, FALSE);
    1761              :          }
    1762              : 
    1763            0 :          if (status == DB_NO_KEY || str[0] == 'y') {
    1764            0 :             compose_name(pwd, param[1], str);
    1765              : 
    1766            0 :             status = db_find_link(hDB, 0, str, &hKey);
    1767            0 :             if (status == DB_SUCCESS) {
    1768            0 :                compose_name(pwd, param[2], str);
    1769              : 
    1770            0 :                db_get_key(hDB, hKey, &key);
    1771            0 :                db_create_key(hDB, 0, str, key.type);
    1772              : 
    1773            0 :                if (key.type != TID_KEY) {
    1774            0 :                   assert(key.total_size > 0);
    1775            0 :                   char *buf = (char *) malloc(key.total_size);
    1776            0 :                   size = key.total_size;
    1777            0 :                   db_get_data(hDB, hKey, buf, &size, key.type);
    1778            0 :                   db_find_key(hDB, 0, str, &hKey);
    1779            0 :                   db_set_link_data(hDB, hKey, buf, size, key.num_values, key.type);
    1780            0 :                   free(buf);
    1781              :                } else {
    1782              :                   char data[50000];
    1783            0 :                   size = sizeof(data);
    1784            0 :                   status = db_copy(hDB, hKey, data, &size, "");
    1785            0 :                   if (status == DB_TRUNCATED) {
    1786            0 :                      printf("error: db_copy() status %d, odbedit internal buffer is too small, size %d\n", status, size);
    1787            0 :                   } else if (status != DB_SUCCESS) {
    1788            0 :                      printf("error: db_copy() status %d\n", status);
    1789              :                   } else {
    1790            0 :                      db_find_key(hDB, 0, str, &hKey);
    1791            0 :                      db_paste(hDB, hKey, data);
    1792              :                   }
    1793              :                }
    1794              :             } else {
    1795            0 :                printf("key not found\n");
    1796              :             }
    1797              :          }
    1798            0 :       }
    1799              : 
    1800              :       /* delete */
    1801            0 :       else if ((param[0][0] == 'd' && param[0][1] == 'e') || (param[0][0] == 'r' && param[0][1] == 'm')) {
    1802            0 :          flags = 0;
    1803            0 :          if ((param[1][0] == '-' && param[1][1] == 'f') || (param[2][0] == '-' && param[2][1] == 'f'))
    1804            0 :             flags |= (1 << 0);
    1805            0 :          if ((param[1][0] == '-' && param[1][1] == 'l') || (param[2][0] == '-' && param[2][1] == 'l'))
    1806            0 :             flags |= (1 << 1);
    1807              : 
    1808            0 :          for (i = 1; param[i][0] == '-'; i++)
    1809              :             ;
    1810              : 
    1811            0 :          compose_name(pwd, param[i], str);
    1812              : 
    1813            0 :          status = db_find_link(hDB, 0, str, &hKey);
    1814            0 :          db_get_key(hDB, hKey, &key);
    1815              : 
    1816            0 :          if (status == DB_SUCCESS) {
    1817            0 :             if (flags & (1 << 0) || cmd_mode)
    1818            0 :                str[0] = 'y';
    1819              :             else {
    1820            0 :                if (key.type == TID_KEY)
    1821            0 :                   printf("Are you sure to delete the key\n\"%s\"\nand all its subkeys? (y/[n]) ",
    1822              :                          str);
    1823              :                else
    1824            0 :                   printf("Are you sure to delete the key\n\"%s\"\n(y/[n]) ", str);
    1825              : 
    1826            0 :                ss_gets(str, 256);
    1827              :             }
    1828              : 
    1829            0 :             if (str[0] == 'y') {
    1830            0 :                status = db_delete_key(hDB, hKey, (flags & (1 << 1)) > 0);
    1831            0 :                if (status == DB_NO_ACCESS) {
    1832            0 :                   printf("deletion of key not allowed\n");
    1833            0 :                } else if (status == DB_OPEN_RECORD) {
    1834            0 :                   printf("key is open by other client\n");
    1835            0 :                } else if (status != DB_SUCCESS) {
    1836            0 :                   printf("Error, db_delete_key() status %d\n", status);
    1837              :                }
    1838              :             }
    1839              :          } else
    1840            0 :             printf("key not found\n");
    1841              :       }
    1842              : 
    1843              :       /* set */
    1844            0 :       else if (param[0][0] == 's' && param[0][1] == 'e') {
    1845              :          /* check if index is supplied */
    1846            0 :          index1 = index2 = 0;
    1847            0 :          strcpy(str, param[1]);
    1848            0 :          strarrayindex(str, &index1, &index2);
    1849            0 :          compose_name(pwd, str, name);
    1850              : 
    1851            0 :          std::vector<HNDLE> keys;
    1852            0 :          status = db_find_keys(hDB, 0, name, keys);
    1853              : 
    1854            0 :          if (status != DB_SUCCESS) {
    1855            0 :             printf("Error: Key \"%s\" not found\n", name);
    1856            0 :             if (cmd_mode)
    1857            0 :                return -1;
    1858              :          } else {
    1859            0 :             for (HNDLE hMatchedKey : keys) {
    1860            0 :                set_key(hDB, hMatchedKey, index1, index2, param[2]);
    1861              :             }
    1862              :          }
    1863            0 :       }
    1864              : 
    1865              :       /* set mode */
    1866            0 :       else if (param[0][0] == 'c' && param[0][1] == 'h' && param[0][2] == 'm') {
    1867            0 :          if (param[1][0] == 0 && param[2][0] == 0) {
    1868            0 :             printf("Please specify mode and key\n");
    1869              :          } else {
    1870            0 :             compose_name(pwd, param[2], str);
    1871              : 
    1872            0 :             mode = atoi(param[1]);
    1873              : 
    1874            0 :             if (strcmp(str, "/") != 0) {
    1875            0 :                status = db_find_key(hDB, 0, str, &hKey);
    1876              :             } else {
    1877            0 :                status = DB_SUCCESS;
    1878            0 :                hKey = 0;
    1879              :             }
    1880              : 
    1881            0 :             if (status == DB_SUCCESS) {
    1882            0 :                if (cmd_mode)
    1883            0 :                   str[0] = 'y';
    1884              :                else {
    1885            0 :                   printf("Are you sure to change the mode of key\n  %s\nand all its subkeys\n",
    1886              :                          str);
    1887            0 :                   printf("to mode [%c%c%c%c]? (y/[n]) ", mode & MODE_READ ? 'R' : 0,
    1888            0 :                          mode & MODE_WRITE ? 'W' : 0, mode & MODE_DELETE ? 'D' : 0,
    1889            0 :                          mode & MODE_EXCLUSIVE ? 'E' : 0);
    1890            0 :                   ss_gets(str, 256);
    1891              :                }
    1892            0 :                if (str[0] == 'y')
    1893            0 :                   db_set_mode(hDB, hKey, mode, TRUE);
    1894              :             } else {
    1895            0 :                printf("Error: Key \"%s\" not found\n", str);
    1896            0 :                if (cmd_mode)
    1897            0 :                   return -1;
    1898              :             }
    1899              :          }
    1900              :       }
    1901              : 
    1902              :       /* test_rpc */
    1903            0 :       else if (strcmp(param[0], "test_rpc") == 0) {
    1904            0 :          status = rpc_test_rpc();
    1905            0 :          if (status == RPC_SUCCESS)
    1906            0 :             printf("RPC test passed!\n");
    1907              :          else
    1908            0 :             printf("RPC test failed!\n");
    1909              :       }
    1910              : 
    1911              :       /* truncate */
    1912            0 :       else if (param[0][0] == 't' && param[0][1] == 'r') {
    1913            0 :          if (param[1][0] == 0) {
    1914            0 :             printf("Please specify key\n");
    1915              :          } else {
    1916            0 :             compose_name(pwd, param[1], str);
    1917              : 
    1918            0 :             status = db_find_key(hDB, 0, str, &hKey);
    1919              : 
    1920            0 :             i = atoi(param[2]);
    1921            0 :             if (i == 0)
    1922            0 :                i = 1;
    1923              : 
    1924            0 :             if (status == DB_SUCCESS)
    1925            0 :                db_set_num_values(hDB, hKey, i);
    1926              :             else {
    1927            0 :                printf("Error: Key \"%s\" not found\n", str);
    1928            0 :                if (cmd_mode)
    1929            0 :                   return -1;
    1930              :             }
    1931              :          }
    1932              :       }
    1933              : 
    1934              :       /* rename */
    1935            0 :       else if (param[0][0] == 'r' && param[0][1] == 'e' && param[0][2] == 'n') {
    1936            0 :          if (param[1][0] == 0) {
    1937            0 :             printf("Please specify key\n");
    1938              :          } else {
    1939            0 :             compose_name(pwd, param[1], str);
    1940              : 
    1941            0 :             if (strcmp(str, "/") != 0)
    1942            0 :                status = db_find_link(hDB, 0, str, &hKey);
    1943              :             else
    1944            0 :                hKey = 0;
    1945              : 
    1946            0 :             if (status == DB_SUCCESS || !hKey)
    1947            0 :                db_rename_key(hDB, hKey, param[2]);
    1948              :             else {
    1949            0 :                printf("Error: Key \"%s\" not found\n", str);
    1950            0 :                if (cmd_mode)
    1951            0 :                   return -1;
    1952              :             }
    1953              :          }
    1954              :       }
    1955              : 
    1956              :       /* move */
    1957            0 :       else if (param[0][0] == 'm' && param[0][1] == 'o') {
    1958            0 :          if (param[1][0] == 0) {
    1959            0 :             printf("Please specify key\n");
    1960              :          } else {
    1961            0 :             compose_name(pwd, param[1], str);
    1962              : 
    1963            0 :             if (strcmp(str, "/") != 0)
    1964            0 :                status = db_find_link(hDB, 0, str, &hKey);
    1965              :             else
    1966            0 :                hKey = 0;
    1967              : 
    1968            0 :             if (status == DB_SUCCESS || !hKey) {
    1969            0 :                if (param[2][0] == 't')
    1970            0 :                   i = 0;
    1971            0 :                else if (param[2][0] == 'b')
    1972            0 :                   i = -1;
    1973              :                else
    1974            0 :                   i = atoi(param[2]);
    1975              : 
    1976            0 :                status = db_reorder_key(hDB, hKey, i);
    1977            0 :                if (status == DB_NO_ACCESS)
    1978            0 :                   printf("no write access to key\n");
    1979            0 :                if (status == DB_OPEN_RECORD)
    1980            0 :                   printf("key is open by other client\n");
    1981              :             } else {
    1982            0 :                printf("Error: Key \"%s\" not found\n", str);
    1983            0 :                if (cmd_mode)
    1984            0 :                   return -1;
    1985              :             }
    1986              :          }
    1987              :       }
    1988              : 
    1989              :       /* find key */
    1990            0 :       else if (param[0][0] == 'f' && param[0][1] == 'i') {
    1991            0 :          status = db_find_key(hDB, 0, pwd, &hKey);
    1992              : 
    1993            0 :          if (status == DB_SUCCESS)
    1994            0 :             db_scan_tree(hDB, hKey, 0, search_key, (void *) param[1]);
    1995              :          else
    1996            0 :             printf("current key is invalid / no read access\n");
    1997              :       }
    1998              : 
    1999              :       /* load */
    2000            0 :       else if (param[0][0] == 'l' && param[0][1] == 'o') {
    2001            0 :          db_find_key(hDB, 0, pwd, &hKey);
    2002              : 
    2003            0 :          db_load(hDB, hKey, param[1], FALSE);
    2004              :       }
    2005              : 
    2006              :       /* save */
    2007            0 :       else if (param[0][0] == 's' && param[0][1] == 'a') {
    2008            0 :          db_find_key(hDB, 0, pwd, &hKey);
    2009              : 
    2010            0 :          if (strstr(param[1], ".xml") || strstr(param[1], ".XML"))
    2011            0 :             db_save_xml(hDB, hKey, param[1]);
    2012            0 :          else if (strstr(param[1], ".json") || strstr(param[1], ".js"))
    2013            0 :             db_save_json(hDB, hKey, param[1]);
    2014            0 :          else if (param[1][0] == '-') {
    2015            0 :             if (param[1][1] == 'c' && param[1][2] == 's') {
    2016            0 :                db_save_struct(hDB, hKey, param[2], NULL, FALSE);
    2017            0 :                db_save_string(hDB, hKey, param[2], NULL, TRUE);
    2018            0 :             } else if (param[1][1] == 'c')
    2019            0 :                db_save_struct(hDB, hKey, param[2], NULL, FALSE);
    2020            0 :             else if (param[1][1] == 's')
    2021            0 :                db_save_string(hDB, hKey, param[2], NULL, FALSE);
    2022            0 :             else if (param[1][1] == 'x')
    2023            0 :                db_save_xml(hDB, hKey, param[2]);
    2024            0 :             else if (param[1][1] == 'j')
    2025            0 :                db_save_json(hDB, hKey, param[2]);
    2026            0 :             else if (param[1][1] == 'z')
    2027            0 :                db_save_json(hDB, hKey, param[2],
    2028              :                             JSFLAG_RECURSE | JSFLAG_OMIT_LAST_WRITTEN | JSFLAG_FOLLOW_LINKS);
    2029              :          } else
    2030            0 :             db_save(hDB, hKey, param[1], FALSE);
    2031              :       }
    2032              : 
    2033              :       /* json */
    2034            0 :       else if (strncmp(param[0], "json", 8) == 0) {
    2035              : 
    2036            0 :          if (param[1][0] == '/') {
    2037            0 :             db_find_key(hDB, 0, param[1], &hKey);
    2038            0 :          } else if (strlen(param[1]) > 0) {
    2039            0 :             db_find_key(hDB, 0, pwd, &hKey);
    2040            0 :             db_find_key(hDB, hKey, param[1], &hKey);
    2041              :          } else {
    2042            0 :             db_find_key(hDB, 0, pwd, &hKey);
    2043              :          }
    2044              : 
    2045            0 :          char *buffer = NULL;
    2046            0 :          int buffer_size = 0;
    2047            0 :          int buffer_end = 0;
    2048              : 
    2049            0 :          status = db_copy_json_save(hDB, hKey, &buffer, &buffer_size, &buffer_end);
    2050              : 
    2051            0 :          printf("status: %d, json: %s\n", status, buffer);
    2052              : 
    2053            0 :          if (buffer)
    2054            0 :             free(buffer);
    2055              :       }
    2056              : 
    2057              :       /* jsvalues */
    2058            0 :       else if (strncmp(param[0], "jsvalues", 8) == 0) {
    2059            0 :          db_find_key(hDB, 0, pwd, &hKey);
    2060              : 
    2061            0 :          char *buffer = NULL;
    2062            0 :          int buffer_size = 0;
    2063            0 :          int buffer_end = 0;
    2064              : 
    2065            0 :          int omit_names = 0;
    2066            0 :          int omit_last_written = 0;
    2067            0 :          time_t omit_old_timestamp = 0;
    2068            0 :          int preserve_case = 0;
    2069              : 
    2070            0 :          status = db_copy_json_values(hDB, hKey, &buffer, &buffer_size, &buffer_end, omit_names, omit_last_written, omit_old_timestamp, preserve_case);
    2071              : 
    2072            0 :          printf("status: %d, json: %s\n", status, buffer);
    2073              : 
    2074            0 :          if (buffer)
    2075            0 :             free(buffer);
    2076              :       }
    2077              : 
    2078              :       /* jsls */
    2079            0 :       else if (strncmp(param[0], "jsls", 4) == 0) {
    2080              : 
    2081            0 :          if (param[1][0] == '/') {
    2082            0 :             db_find_key(hDB, 0, param[1], &hKey);
    2083            0 :          } else if (strlen(param[1]) > 0) {
    2084            0 :             db_find_key(hDB, 0, pwd, &hKey);
    2085            0 :             db_find_key(hDB, hKey, param[1], &hKey);
    2086              :          } else {
    2087            0 :             db_find_key(hDB, 0, pwd, &hKey);
    2088              :          }
    2089              : 
    2090            0 :          char *buffer = NULL;
    2091            0 :          int buffer_size = 0;
    2092            0 :          int buffer_end = 0;
    2093              : 
    2094            0 :          status = db_copy_json_ls(hDB, hKey, &buffer, &buffer_size, &buffer_end);
    2095              : 
    2096            0 :          printf("jsls \"%s\", status: %d, json: %s\n", pwd, status, buffer);
    2097              : 
    2098            0 :          if (buffer)
    2099            0 :             free(buffer);
    2100              :       }
    2101              : 
    2102              :       /* make */
    2103            0 :       else if (param[0][0] == 'm' && param[0][1] == 'a') {
    2104            0 :          if (param[1][0])
    2105            0 :             create_experim_h(hDB, param[1]);
    2106              :          else
    2107            0 :             create_experim_h(hDB, "Analyzer");
    2108              :       }
    2109              : 
    2110              :       /* passwd */
    2111            0 :       else if (param[0][0] == 'p' && param[0][1] == 'a' && param[0][2] == 's') {
    2112              :          /*
    2113              :             strcpy(str, ss_crypt("foob", "ar"));
    2114              :             if(strcmp(str, "arlEKn0OzVJn.") != 0)
    2115              :             printf("Warning: ss_crypt() works incorrect");
    2116              :           */
    2117              : 
    2118            0 :          if (db_find_key(hDB, 0, "/Experiment/Security/Password", &hKey) == DB_SUCCESS) {
    2119            0 :             size = sizeof(old_password);
    2120            0 :             db_get_data(hDB, hKey, old_password, &size, TID_STRING);
    2121              : 
    2122            0 :             strcpy(str, ss_getpass("Old password: "));
    2123            0 :             strcpy(str, ss_crypt(str, "mi"));
    2124              : 
    2125            0 :             if (strcmp(str, old_password) == 0 || strcmp(str, "mid7qBxsNMHux") == 0) {
    2126            0 :                strcpy(str, ss_getpass("New password: "));
    2127            0 :                strcpy(new_password, ss_crypt(str, "mi"));
    2128              : 
    2129            0 :                strcpy(str, ss_getpass("Retype new password: "));
    2130            0 :                if (strcmp(new_password, ss_crypt(str, "mi")) != 0)
    2131            0 :                   printf("Mismatch - password unchanged\n");
    2132              :                else
    2133            0 :                   db_set_data(hDB, hKey, new_password, 32, 1, TID_STRING);
    2134              :             } else
    2135            0 :                printf("Wrong password\n");
    2136              :          } else {
    2137            0 :             strcpy(str, ss_getpass("Password: "));
    2138            0 :             strcpy(new_password, ss_crypt(str, "mi"));
    2139              : 
    2140            0 :             strcpy(str, ss_getpass("Retype password: "));
    2141            0 :             if (strcmp(new_password, ss_crypt(str, "mi")) != 0)
    2142            0 :                printf("Mismatch - password not set\n");
    2143              :             else {
    2144              :                /* set password */
    2145            0 :                db_set_value(hDB, 0, "/Experiment/Security/Password", new_password, 32, 1,
    2146              :                             TID_STRING);
    2147              : 
    2148              :                /* create empty allowed hosts and allowd programs entries */
    2149            0 :                db_create_key(hDB, 0,
    2150              :                              "/Experiment/Security/Allowed hosts/host.sample.domain",
    2151              :                              TID_INT);
    2152            0 :                db_create_key(hDB, 0, "/Experiment/Security/Allowed programs/mstat",
    2153              :                              TID_INT);
    2154              :             }
    2155              :          }
    2156              : 
    2157              :       }
    2158              : 
    2159              :       /* webpasswd */
    2160            0 :       else if (param[0][0] == 'w' && param[0][1] == 'e' && param[0][2] == 'b') {
    2161            0 :          if (db_find_key(hDB, 0, "/Experiment/Security/Web Password", &hKey) == DB_SUCCESS) {
    2162            0 :             size = sizeof(old_password);
    2163            0 :             db_get_data(hDB, hKey, old_password, &size, TID_STRING);
    2164              : 
    2165            0 :             strcpy(str, ss_getpass("Old password: "));
    2166            0 :             strcpy(str, ss_crypt(str, "mi"));
    2167              : 
    2168            0 :             if (strcmp(str, old_password) == 0 || strcmp(str, "mid7qBxsNMHux") == 0) {
    2169            0 :                strcpy(str, ss_getpass("New password: "));
    2170            0 :                strcpy(new_password, ss_crypt(str, "mi"));
    2171              : 
    2172            0 :                strcpy(str, ss_getpass("Retype new password: "));
    2173            0 :                if (strcmp(new_password, ss_crypt(str, "mi")) != 0)
    2174            0 :                   printf("Mismatch - password unchanged\n");
    2175              :                else
    2176            0 :                   db_set_data(hDB, hKey, new_password, 32, 1, TID_STRING);
    2177              :             } else
    2178            0 :                printf("Wrong password\n");
    2179              :          } else {
    2180            0 :             strcpy(str, ss_getpass("Password: "));
    2181            0 :             strcpy(new_password, ss_crypt(str, "mi"));
    2182              : 
    2183            0 :             strcpy(str, ss_getpass("Retype password: "));
    2184            0 :             if (strcmp(new_password, ss_crypt(str, "mi")) != 0)
    2185            0 :                printf("Mismatch - password not set\n");
    2186              :             else
    2187              :                /* set password */
    2188            0 :                db_set_value(hDB, 0, "/Experiment/Security/Web Password", new_password, 32,
    2189              :                             1, TID_STRING);
    2190              :          }
    2191              :       }
    2192              : 
    2193              :       /* hi */
    2194            0 :       else if (param[0][0] == 'h' && param[0][1] == 'i') {
    2195              :          HNDLE hConn;
    2196              : 
    2197            0 :          client_name[0] = 0;
    2198              : 
    2199            0 :          if (!isalpha(param[1][0])) {
    2200              :             /* find client which exports RPC_ANA_CLEAR_HISTOS */
    2201            0 :             status = db_find_key(hDB, 0, "System/Clients", &hRootKey);
    2202            0 :             if (status == DB_SUCCESS) {
    2203            0 :                for (i = 0;; i++) {
    2204            0 :                   status = db_enum_key(hDB, hRootKey, i, &hSubkey);
    2205            0 :                   if (status == DB_NO_MORE_SUBKEYS) {
    2206            0 :                      printf("No client currently exports the CLEAR HISTO functionality.\n");
    2207            0 :                      break;
    2208              :                   }
    2209              : 
    2210            0 :                   sprintf(str, "RPC/%d", RPC_ANA_CLEAR_HISTOS);
    2211            0 :                   status = db_find_key(hDB, hSubkey, str, &hKey);
    2212            0 :                   if (status == DB_SUCCESS) {
    2213            0 :                      size = sizeof(client_name);
    2214            0 :                      db_get_value(hDB, hSubkey, "Name", client_name, &size, TID_STRING,
    2215              :                                   TRUE);
    2216            0 :                      break;
    2217              :                   }
    2218              :                }
    2219              :             }
    2220              : 
    2221            0 :             if (isdigit(param[1][0]))
    2222            0 :                n1 = atoi(param[1]);
    2223              :             else
    2224            0 :                n1 = 0; /* all histos by default */
    2225              : 
    2226            0 :             if (isdigit(param[2][0]))
    2227            0 :                n2 = atoi(param[2]);
    2228              :             else
    2229            0 :                n2 = n1; /* single histo by default */
    2230              :          } else {
    2231            0 :             strcpy(client_name, param[1]);
    2232              : 
    2233            0 :             if (isdigit(param[2][0]))
    2234            0 :                n1 = atoi(param[2]);
    2235              :             else
    2236            0 :                n1 = 0; /* all histos by default */
    2237              : 
    2238            0 :             if (isdigit(param[3][0]))
    2239            0 :                n2 = atoi(param[3]);
    2240              :             else
    2241            0 :                n2 = n1; /* single histo by default */
    2242              :          }
    2243              : 
    2244            0 :          if (client_name[0]) {
    2245            0 :             if (cm_connect_client(client_name, &hConn) == CM_SUCCESS) {
    2246            0 :                rpc_client_call(hConn, RPC_ANA_CLEAR_HISTOS, n1, n2);
    2247              :                //cm_disconnect_client(hConn, FALSE);
    2248              :             } else
    2249            0 :                printf("Cannot connect to client %s\n", client_name);
    2250              :          }
    2251            0 :       }
    2252              : 
    2253              :       /* import */
    2254            0 :       else if (param[0][0] == 'i' && param[0][1] == 'm') {
    2255            0 :          int fh = open(param[1], O_RDONLY | O_TEXT);
    2256            0 :          if (fh < 0) {
    2257            0 :             printf("Could not open file \"%s\", errno %d (%s)\n", param[1], errno, strerror(errno));
    2258              :          } else {
    2259            0 :             off_t off = lseek(fh, 0, SEEK_END);
    2260            0 :             if (off < 0) {
    2261            0 :                printf("Could not get size of file \"%s\", lseek(SEEK_END) errno %d (%s)\n", param[1], errno, strerror(errno));
    2262            0 :                close(fh);
    2263              :             } else {
    2264            0 :                lseek(fh, 0, SEEK_SET);
    2265            0 :                size_t size = off;
    2266            0 :                char *buf = (char *) malloc(size + 1);
    2267            0 :                ssize_t rd = read(fh, buf, size);
    2268            0 :                if (rd < 0) {
    2269            0 :                   printf("Could not read file \"%s\", read(%zu) errno %d (%s)\n", param[1], size, errno, strerror(errno));
    2270            0 :                   close(fh);
    2271            0 :                   free(buf);
    2272              :                } else {
    2273            0 :                   close(fh);
    2274            0 :                   size = rd;
    2275            0 :                   if (size == 0) {
    2276            0 :                      buf[size] = 0;
    2277            0 :                      size++;
    2278            0 :                   } else if (buf[size - 1] != 0) {
    2279            0 :                      buf[size] = 0;
    2280            0 :                      size++;
    2281              :                   }
    2282              : 
    2283            0 :                   if (param[2][0] == 0) {
    2284            0 :                      printf("Key name: ");
    2285            0 :                      ss_gets(name, 256);
    2286              :                   } else {
    2287            0 :                      strcpy(name, param[2]);
    2288              :                   }
    2289              : 
    2290            0 :                   compose_name(pwd, name, str);
    2291              :                   
    2292            0 :                   db_create_key(hDB, 0, str, TID_STRING);
    2293            0 :                   db_find_key(hDB, 0, str, &hKey);
    2294            0 :                   db_set_data(hDB, hKey, buf, size, 1, TID_STRING);
    2295            0 :                   free(buf);
    2296              :                }
    2297              :             }
    2298              :          }
    2299              : 
    2300            0 :       }
    2301              : 
    2302              :       /* export */
    2303            0 :       else if (param[0][0] == 'e' && param[0][1] == 'x' && param[0][2] == 'p') {
    2304              :          FILE *f;
    2305              : 
    2306            0 :          if (param[1][0] == 0)
    2307            0 :             printf("please specify key\n");
    2308              :          else {
    2309            0 :             compose_name(pwd, param[1], str);
    2310              : 
    2311            0 :             db_find_key(hDB, 0, str, &hKey);
    2312            0 :             if (hKey == 0)
    2313            0 :                printf("Error: Key \"%s\" not found\n", param[1]);
    2314              :             else {
    2315            0 :                if (param[2][0] == 0) {
    2316            0 :                   printf("File name: ");
    2317            0 :                   ss_gets(name, 256);
    2318              :                } else
    2319            0 :                   strcpy(name, param[2]);
    2320              : 
    2321            0 :                f = fopen(name, "w");
    2322            0 :                if (f == NULL)
    2323            0 :                   printf("Cannot open file \"%s\"\n", name);
    2324              :                else {
    2325            0 :                   db_get_key(hDB, hKey, &key);
    2326            0 :                   if (key.type != TID_STRING)
    2327            0 :                      printf("Only export of STRING key possible\n");
    2328              :                   else {
    2329            0 :                      char *buf = (char *) malloc(key.total_size);
    2330            0 :                      size = key.total_size;
    2331            0 :                      memset(buf, 0, size);
    2332            0 :                      db_get_data(hDB, hKey, buf, &size, key.type);
    2333            0 :                      fprintf(f, "%s", buf);
    2334            0 :                      fclose(f);
    2335            0 :                      free(buf);
    2336              :                   }
    2337              :                }
    2338              :             }
    2339              :          }
    2340            0 :       }
    2341              : 
    2342              :       /* alarm reset */
    2343            0 :       else if (param[0][0] == 'a' && param[0][1] == 'l') {
    2344              :          /* go through all alarms */
    2345            0 :          db_find_key(hDB, 0, "/Alarms/Alarms", &hKey);
    2346            0 :          if (hKey) {
    2347            0 :             for (i = 0;; i++) {
    2348            0 :                db_enum_link(hDB, hKey, i, &hSubkey);
    2349              : 
    2350            0 :                if (!hSubkey)
    2351            0 :                   break;
    2352              : 
    2353            0 :                db_get_key(hDB, hSubkey, &key);
    2354            0 :                status = al_reset_alarm(key.name);
    2355            0 :                if (status == AL_RESET)
    2356            0 :                   printf("Alarm of class \"%s\" reset sucessfully\n", key.name);
    2357              :             }
    2358              :          }
    2359              :       }
    2360              : 
    2361              :       /* mem */
    2362            0 :       else if (param[0][0] == 'm' && param[0][1] == 'e') {
    2363            0 :          if (rpc_is_remote())
    2364            0 :             printf("This function works only locally\n");
    2365              :          else {
    2366              : #ifdef LOCAL_ROUTINES
    2367            0 :             char *buf = NULL;
    2368            0 :             db_show_mem(hDB, &buf, param[1][0]);
    2369            0 :             if (buf) {
    2370            0 :                puts(buf);
    2371            0 :                free(buf);
    2372              :             }
    2373              : #else
    2374              :             printf("This MIDAS only works remotely\n");
    2375              : #endif// LOCAL_ROUTINES
    2376              :          }
    2377            0 :       }
    2378              : 
    2379              :       /* sor (show open records) */
    2380            0 :       else if (param[0][0] == 's' && param[0][1] == 'o') {
    2381            0 :          db_find_key(hDB, 0, pwd, &hKey);
    2382              :          char data[50000];
    2383            0 :          db_get_open_records(hDB, hKey, data, sizeof(data), FALSE);
    2384            0 :          printf("%s", data);
    2385            0 :       }
    2386              : 
    2387              :       /* scl (show clients ) */
    2388            0 :       else if (param[0][0] == 's' && param[0][1] == 'c') {
    2389            0 :          status = db_find_key(hDB, 0, "System/Clients", &hKey);
    2390            0 :          if (status != DB_SUCCESS)
    2391            0 :             cm_msg(MERROR, "command_loop",
    2392              :                    "cannot find System/Clients entry in database");
    2393              :          else {
    2394            0 :             if (param[1][1] == 'w')
    2395            0 :                printf("Name                Host                Timeout    Last called\n");
    2396              :             else
    2397            0 :                printf("Name                Host\n");
    2398              : 
    2399              :             /* search database for clients with transition mask set */
    2400            0 :             for (i = 0, status = 0;; i++) {
    2401            0 :                status = db_enum_key(hDB, hKey, i, &hSubkey);
    2402            0 :                if (status == DB_NO_MORE_SUBKEYS)
    2403            0 :                   break;
    2404              : 
    2405            0 :                if (status == DB_SUCCESS) {
    2406            0 :                   size = sizeof(name);
    2407            0 :                   db_get_value(hDB, hSubkey, "Name", name, &size, TID_STRING, TRUE);
    2408            0 :                   printf("%s", name);
    2409            0 :                   for (int j = 0; j < 20 - (int) strlen(name); j++)
    2410            0 :                      printf(" ");
    2411              : 
    2412            0 :                   size = sizeof(str);
    2413            0 :                   db_get_value(hDB, hSubkey, "Host", str, &size, TID_STRING, TRUE);
    2414            0 :                   printf("%s", str);
    2415            0 :                   for (int j = 0; j < 20 - (int) strlen(str); j++)
    2416            0 :                      printf(" ");
    2417              : 
    2418              :                   /* display optional watchdog info */
    2419            0 :                   if (param[1][1] == 'w') {
    2420              :                      DWORD timeout, last;
    2421              : 
    2422            0 :                      status = cm_get_watchdog_info(hDB, name, &timeout, &last);
    2423            0 :                      printf("%-10d %-10d", timeout, last);
    2424              :                   }
    2425              : 
    2426            0 :                   printf("\n");
    2427              :                }
    2428            0 :             }
    2429              :          }
    2430            0 :       }
    2431              : 
    2432              :       /* start */
    2433            0 :       else if (param[0][0] == 's' && param[0][1] == 't' && param[0][2] == 'a') {
    2434            0 :          debug_flag = ((param[1][0] == '-' && param[1][1] == 'v') || (param[2][0] == '-' && param[2][1] == 'v') || (param[3][0] == '-' && param[3][1] == 'v'));
    2435            0 :          mthread_flag = ((param[1][0] == '-' && param[1][1] == 'm') || (param[2][0] == '-' && param[2][1] == 'm') || (param[3][0] == '-' && param[3][1] == 'm'));
    2436              : 
    2437              :          /* check if run is already started */
    2438            0 :          size = sizeof(i);
    2439            0 :          i = STATE_STOPPED;
    2440            0 :          db_get_value(hDB, 0, "/Runinfo/State", &i, &size, TID_INT, TRUE);
    2441            0 :          if (i == STATE_RUNNING) {
    2442            0 :             printf("Run is already started\n");
    2443            0 :          } else if (i == STATE_PAUSED) {
    2444            0 :             printf("Run is paused, please use \"resume\"\n");
    2445              :          } else {
    2446              :             /* get present run number */
    2447            0 :             old_run_number = 0;
    2448            0 :             status = db_get_value(hDB, 0, "/Runinfo/Run number", &old_run_number, &size, TID_INT, TRUE);
    2449            0 :             assert(status == SUCCESS);
    2450            0 :             assert(old_run_number >= 0);
    2451              : 
    2452              :             /* edit run parameter if command is not "start now" */
    2453            0 :             if ((param[1][0] == 'n' && param[1][1] == 'o' && param[1][2] == 'w') || cmd_mode) {
    2454            0 :                new_run_number = old_run_number + 1;
    2455            0 :                line[0] = 'y';
    2456              :             } else {
    2457            0 :                db_find_key(hDB, 0, "/Experiment/Edit on start", &hKey);
    2458              :                do {
    2459            0 :                   if (hKey) {
    2460            0 :                      for (i = 0;; i++) {
    2461            0 :                         db_enum_link(hDB, hKey, i, &hSubkey);
    2462              : 
    2463            0 :                         if (!hSubkey)
    2464            0 :                            break;
    2465              : 
    2466            0 :                         db_get_key(hDB, hSubkey, &key);
    2467            0 :                         std::string str = key.name;
    2468              : 
    2469            0 :                         if (equal_ustring(str.c_str(), "Edit run number"))
    2470            0 :                            continue;
    2471              : 
    2472            0 :                         if (str.find("Options ") == 0)
    2473            0 :                            continue;
    2474              : 
    2475            0 :                         db_enum_key(hDB, hKey, i, &hSubkey);
    2476            0 :                         db_get_key(hDB, hSubkey, &key);
    2477              : 
    2478            0 :                         assert(key.total_size > 0);
    2479            0 :                         char *buf = (char *) malloc(key.total_size);
    2480              : 
    2481            0 :                         size = key.total_size;
    2482            0 :                         status = db_get_data(hDB, hSubkey, buf, &size, key.type);
    2483            0 :                         if (status != DB_SUCCESS) {
    2484            0 :                            free(buf);
    2485            0 :                            continue;
    2486              :                         }
    2487              : 
    2488            0 :                         for (int j = 0; j < key.num_values; j++) {
    2489            0 :                            std::string xdata_str = db_sprintf(buf, key.item_size, j, key.type);
    2490            0 :                            std::string xprompt;
    2491            0 :                            xprompt += str;
    2492            0 :                            if (key.num_values == 1) {
    2493            0 :                               xprompt += " : ";
    2494              :                            } else {
    2495            0 :                               xprompt += msprintf("[%d] : ", j);
    2496              :                            }
    2497              : 
    2498            0 :                            strcpy(line, xdata_str.c_str());// FIXME: buffer overflow. K.O. aug2024
    2499            0 :                            in_cmd_edit = TRUE;
    2500            0 :                            cmd_edit(xprompt.c_str(), line, NULL, cmd_idle);
    2501            0 :                            in_cmd_edit = FALSE;
    2502              : 
    2503            0 :                            if (line[0]) {
    2504            0 :                               db_sscanf(line, buf, &size, j, key.type);
    2505            0 :                               db_set_data_index(hDB, hSubkey, buf, key.item_size, j, key.type);
    2506              :                            }
    2507            0 :                         }
    2508              : 
    2509            0 :                         free(buf);
    2510            0 :                      }
    2511              :                   }
    2512              : 
    2513              :                   /* increment run number */
    2514            0 :                   new_run_number = old_run_number + 1;
    2515              : 
    2516            0 :                   if (db_find_key(hDB, 0, "/Experiment/Edit on start/Edit Run number", &hKey) == DB_SUCCESS && db_get_data(hDB, hKey, &i, &size, TID_BOOL) && i == 0) {
    2517            0 :                      printf("Run number: %d\n", new_run_number);
    2518              :                   } else {
    2519              : 
    2520            0 :                      printf("Run number [%d]: ", new_run_number);
    2521            0 :                      ss_gets(line, 256);
    2522            0 :                      if (line[0] && atoi(line) > 0)
    2523            0 :                         new_run_number = atoi(line);
    2524              :                   }
    2525              : 
    2526            0 :                   printf("Are the above parameters correct? ([y]/n/q): ");
    2527            0 :                   ss_gets(line, 256);
    2528              : 
    2529            0 :                } while (line[0] == 'n' || line[0] == 'N');
    2530              :             }
    2531              : 
    2532            0 :             if (line[0] != 'q' && line[0] != 'Q') {
    2533              :                /* start run */
    2534            0 :                printf("Starting run #%d\n", new_run_number);
    2535              : 
    2536            0 :                assert(new_run_number > 0);
    2537              : 
    2538            0 :                status = cm_transition(TR_START, new_run_number, str,
    2539              :                                       sizeof(str), mthread_flag ? TR_MTHREAD | TR_SYNC : TR_SYNC, debug_flag);
    2540            0 :                if (status != CM_SUCCESS) {
    2541              :                   /* in case of error, reset run number */
    2542              :                   status =
    2543            0 :                      db_set_value(hDB, 0, "/Runinfo/Run number", &old_run_number,
    2544              :                                   sizeof(old_run_number), 1, TID_INT);
    2545            0 :                   assert(status == SUCCESS);
    2546              : 
    2547            0 :                   printf("Error: %s\n", str);
    2548              :                }
    2549              :             }
    2550              :          }
    2551            0 :       }
    2552              : 
    2553              :       /* stop */
    2554            0 :       else if (param[0][0] == 's' && param[0][1] == 't' && param[0][2] == 'o') {
    2555            0 :          debug_flag = ((param[1][0] == '-' && param[1][1] == 'v') || (param[2][0] == '-' && param[2][1] == 'v') || (param[3][0] == '-' && param[3][1] == 'v'));
    2556            0 :          mthread_flag = ((param[1][0] == '-' && param[1][1] == 'm') || (param[2][0] == '-' && param[2][1] == 'm') || (param[3][0] == '-' && param[3][1] == 'm'));
    2557              : 
    2558              :          /* check if run is stopped */
    2559            0 :          state = STATE_STOPPED;
    2560            0 :          size = sizeof(i);
    2561            0 :          db_get_value(hDB, 0, "/Runinfo/State", &state, &size, TID_INT, TRUE);
    2562            0 :          str[0] = 0;
    2563            0 :          if (state == STATE_STOPPED && !cmd_mode) {
    2564            0 :             printf("Run is already stopped. Stop again? (y/[n]) ");
    2565            0 :             ss_gets(str, 256);
    2566              :          }
    2567            0 :          if (str[0] == 'y' || state != STATE_STOPPED || cmd_mode) {
    2568            0 :             if (param[1][0] == 'n')
    2569              :                status =
    2570            0 :                   cm_transition(TR_STOP | TR_DEFERRED, 0, str, sizeof(str), mthread_flag ? TR_MTHREAD | TR_SYNC : TR_SYNC, debug_flag);
    2571              :             else
    2572            0 :                status = cm_transition(TR_STOP, 0, str, sizeof(str), mthread_flag ? TR_MTHREAD | TR_SYNC : TR_SYNC, debug_flag);
    2573              : 
    2574            0 :             if (status == CM_DEFERRED_TRANSITION)
    2575            0 :                printf("%s\n", str);
    2576            0 :             else if (status == CM_TRANSITION_IN_PROGRESS)
    2577            0 :                printf("Deferred stop already in progress, enter \"stop now\" to force stop\n");
    2578            0 :             else if (status != CM_SUCCESS)
    2579            0 :                printf("Error: %s\n", str);
    2580              :          }
    2581              :       }
    2582              : 
    2583              :       /* pause */
    2584            0 :       else if (param[0][0] == 'p' && param[0][1] == 'a' && param[0][2] == 'u') {
    2585            0 :          debug_flag = ((param[1][0] == '-' && param[1][1] == 'v') || (param[2][0] == '-' && param[2][1] == 'v'));
    2586              : 
    2587              :          /* check if run is started */
    2588            0 :          i = STATE_STOPPED;
    2589            0 :          size = sizeof(i);
    2590            0 :          db_get_value(hDB, 0, "/Runinfo/State", &i, &size, TID_INT, TRUE);
    2591            0 :          if (i != STATE_RUNNING) {
    2592            0 :             printf("Run is not started\n");
    2593              :          } else {
    2594            0 :             if (param[1][0] == 'n')
    2595            0 :                status = cm_transition(TR_PAUSE | TR_DEFERRED, 0, str, sizeof(str), TR_SYNC, debug_flag);
    2596              :             else
    2597            0 :                status = cm_transition(TR_PAUSE, 0, str, sizeof(str), TR_SYNC, debug_flag);
    2598              : 
    2599            0 :             if (status == CM_DEFERRED_TRANSITION)
    2600            0 :                printf("%s\n", str);
    2601            0 :             else if (status == CM_TRANSITION_IN_PROGRESS)
    2602            0 :                printf("Deferred pause already in progress, enter \"pause now\" to force pause\n");
    2603            0 :             else if (status != CM_SUCCESS)
    2604            0 :                printf("Error: %s\n", str);
    2605              :          }
    2606              :       }
    2607              : 
    2608              :       /* resume */
    2609            0 :       else if (param[0][0] == 'r' && param[0][1] == 'e' && param[0][2] == 's') {
    2610            0 :          debug_flag = ((param[1][0] == '-' && param[1][1] == 'v') || (param[2][0] == '-' && param[2][1] == 'v'));
    2611              : 
    2612              :          /* check if run is paused */
    2613            0 :          i = STATE_STOPPED;
    2614            0 :          size = sizeof(i);
    2615            0 :          db_get_value(hDB, 0, "/Runinfo/State", &i, &size, TID_INT, TRUE);
    2616            0 :          if (i != STATE_PAUSED) {
    2617            0 :             printf("Run is not paused\n");
    2618              :          } else {
    2619            0 :             status = cm_transition(TR_RESUME, 0, str, sizeof(str), TR_SYNC, debug_flag);
    2620            0 :             if (status != CM_SUCCESS)
    2621            0 :                printf("Error: %s\n", str);
    2622              :          }
    2623              :       }
    2624              : 
    2625              :       /* msg */
    2626            0 :       else if (param[0][0] == 'm' && param[0][1] == 's') {
    2627              :          // param[1]: facility, param[2]: type, param[3]: name  param[4]: message
    2628            0 :          if (!param[4][0]) {
    2629            0 :             printf("Error: Not enough parameters. Please use\n\n");
    2630            0 :             printf("   msg <facility> <type> <name> <message>\n\n");
    2631            0 :             printf("where <facility> can be \"midas\", \"chat\", ...\n");
    2632            0 :             printf("and <type> must be \"error\", \"info\", \"debug\", \"user\", \"log\", \"talk\" or \"call\".\n");
    2633              :          } else {
    2634            0 :             int type = 0;
    2635            0 :             if (equal_ustring(param[2], MT_ERROR_STR))
    2636            0 :                type = MT_ERROR;
    2637            0 :             if (equal_ustring(param[2], MT_INFO_STR))
    2638            0 :                type = MT_INFO;
    2639            0 :             if (equal_ustring(param[2], MT_DEBUG_STR))
    2640            0 :                type = MT_DEBUG;
    2641            0 :             if (equal_ustring(param[2], MT_USER_STR))
    2642            0 :                type = MT_USER;
    2643            0 :             if (equal_ustring(param[2], MT_LOG_STR))
    2644            0 :                type = MT_LOG;
    2645            0 :             if (equal_ustring(param[2], MT_TALK_STR))
    2646            0 :                type = MT_TALK;
    2647            0 :             if (equal_ustring(param[2], MT_CALL_STR))
    2648            0 :                type = MT_CALL;
    2649            0 :             if (type == 0) {
    2650            0 :                printf("Error: inavlid type \"%s\".\n", param[2]);
    2651            0 :                printf("<type> must be one of \"error\", \"info\", \"debug\", \"user\", \"log\", \"talk\", \"call\".\n");
    2652              :             } else {
    2653              : 
    2654            0 :                cm_msg1(type, __FILE__, __LINE__, param[1], param[3], "%s", param[4]);
    2655            0 :                last_msg_time = ss_time();
    2656              :             }
    2657              :          }
    2658            0 :       }
    2659              : 
    2660              :       /* chat */
    2661            0 :       else if (param[0][0] == 'c' && param[0][1] == 'h' && param[0][2] == 'a') {
    2662            0 :          message[0] = 0;
    2663              : 
    2664            0 :          if (ss_time() - last_msg_time > 300) {
    2665            0 :             printf("Your name> ");
    2666            0 :             ss_gets(user_name, 80);
    2667              :          }
    2668              : 
    2669            0 :          printf("Exit chat mode with empty line.\n");
    2670              :          do {
    2671            0 :             in_cmd_edit = TRUE;
    2672            0 :             message[0] = 0;
    2673            0 :             cmd_edit("> ", message, NULL, cmd_idle);
    2674            0 :             in_cmd_edit = FALSE;
    2675              : 
    2676            0 :             if (message[0])
    2677            0 :                cm_msg1(MUSER, "chat", user_name, "%s", message);
    2678              : 
    2679            0 :          } while (message[0]);
    2680              : 
    2681            0 :          last_msg_time = ss_time();
    2682              :       }
    2683              : 
    2684              :       /* old */
    2685            0 :       else if (param[0][0] == 'o' && param[0][1] == 'l') {
    2686            0 :          i = 20;
    2687            0 :          if (param[1][0])
    2688            0 :             i = atoi(param[1]);
    2689              : 
    2690              :          char data[50000];
    2691            0 :          cm_msg_retrieve(i, data, sizeof(data));
    2692            0 :          printf("%s\n\n", data);
    2693            0 :       }
    2694              : 
    2695              :       /* cleanup */
    2696            0 :       else if (param[0][0] == 'c' && param[0][1] == 'l') {
    2697              :          HNDLE hBuf;
    2698              :          BOOL force;
    2699              : 
    2700            0 :          force = FALSE;
    2701            0 :          if (param[1][0] == '-' && param[1][1] == 'f')
    2702            0 :             force = TRUE;
    2703            0 :          if (param[2][0] == '-' && param[2][1] == 'f')
    2704            0 :             force = TRUE;
    2705              : 
    2706            0 :          bm_open_buffer(EVENT_BUFFER_NAME, DEFAULT_BUFFER_SIZE, &hBuf);
    2707              : 
    2708            0 :          if (param[1][0] && param[1][0] != '-')
    2709            0 :             cm_cleanup(param[1], force);
    2710              :          else
    2711            0 :             cm_cleanup("", force);
    2712            0 :          bm_close_buffer(hBuf);
    2713            0 :       }
    2714              : 
    2715              :       /* shutdown */
    2716            0 :       else if (param[0][0] == 's' && param[0][1] == 'h') {
    2717            0 :          if (param[1][0] == 0)
    2718            0 :             printf("Please enter client name or \"all\" to shutdown all clients.\n");
    2719              :          else {
    2720            0 :             status = cm_shutdown(param[1], TRUE);
    2721            0 :             if (status != CM_SUCCESS) {
    2722            0 :                if (strcmp(param[1], "all") == 0)
    2723            0 :                   printf("No clients found\n");
    2724              :                else
    2725            0 :                   printf("Client \"%s\" not active\n", param[1]);
    2726              :             }
    2727              :          }
    2728              :       }
    2729              : 
    2730              :       /* ver */
    2731            0 :       else if (param[0][0] == 'v' && param[0][1] == 'e') {
    2732            0 :          printf("MIDAS version:      %s\n", cm_get_version());
    2733            0 :          printf("GIT revision:       %s\n", cm_get_revision());
    2734            0 :          printf("ODB version:        %d\n", DATABASE_VERSION);
    2735              :       }
    2736              : 
    2737              :       /* exec */
    2738            0 :       else if (param[0][0] == 'e' && param[0][1] == 'x' && param[0][2] == 'e') {
    2739            0 :          compose_name(pwd, param[1], str);
    2740              :          char data[50000];
    2741            0 :          status = db_find_key(hDB, 0, str, &hKey);
    2742            0 :          if (status == DB_SUCCESS) {
    2743            0 :             db_get_key(hDB, hKey, &key);
    2744            0 :             if (key.type != TID_STRING) {
    2745            0 :                printf("Key contains no command\n");
    2746            0 :                continue;
    2747              :             }
    2748            0 :             size = sizeof(str);
    2749            0 :             db_get_data(hDB, hKey, str, &size, key.type);
    2750              : 
    2751            0 :             cm_execute(str, data, sizeof(data));
    2752              :          } else {
    2753            0 :             cm_execute(param[1], data, sizeof(data));
    2754              :          }
    2755            0 :          puts(data);
    2756            0 :       }
    2757              : 
    2758              :       /* wait */
    2759            0 :       else if (param[0][0] == 'w' && param[0][1] == 'a' && param[0][2] == 'i') {
    2760            0 :          if (param[1][0] == 0) {
    2761            0 :             printf("Please specify key\n");
    2762              :          } else {
    2763            0 :             compose_name(pwd, param[1], str);
    2764              : 
    2765            0 :             if (equal_ustring(str, "/")) {
    2766            0 :                status = DB_SUCCESS;
    2767            0 :                status = db_find_link(hDB, 0, "/", &hKey);
    2768              :             } else
    2769            0 :                status = db_find_link(hDB, 0, str, &hKey);
    2770              : 
    2771            0 :             if (status == DB_SUCCESS) {
    2772            0 :                db_get_key(hDB, hKey, &key);
    2773            0 :                printf("Waiting for key \"%s\" to be modified, abort with any key\n", key.name);
    2774            0 :                db_get_record_size(hDB, hKey, 0, &size);
    2775            0 :                char *buf = (char *) malloc(size);
    2776            0 :                key_modified = FALSE;
    2777            0 :                db_open_record(hDB, hKey, buf, size, MODE_READ, key_update, NULL);
    2778              : 
    2779              :                do {
    2780            0 :                   status = cm_yield(1000);
    2781            0 :                   if (status == SS_ABORT || status == RPC_SHUTDOWN)
    2782              :                      break;
    2783            0 :                } while (!key_modified && !ss_kbhit());
    2784              : 
    2785            0 :                while (ss_kbhit())
    2786            0 :                   ss_getchar(0);
    2787              : 
    2788            0 :                db_close_record(hDB, hKey);
    2789            0 :                if (buf) {
    2790            0 :                   free(buf);
    2791            0 :                   buf = NULL;
    2792              :                }
    2793              : 
    2794            0 :                if (status == SS_ABORT || status == RPC_SHUTDOWN)
    2795              :                   break;
    2796              : 
    2797            0 :                if (i == '!')
    2798            0 :                   printf("Wait aborted.\n");
    2799              :                else
    2800            0 :                   printf("Key has been modified.\n");
    2801              :             } else
    2802            0 :                printf("key \"%s\" not found\n", str);
    2803              :          }
    2804            0 :       }
    2805              : 
    2806              :       /* watch */
    2807            0 :       else if (param[0][0] == 'w' && param[0][1] == 'a' && param[0][2] == 't') {
    2808            0 :          if (param[1][0] == 0) {
    2809            0 :             printf("Please specify key\n");
    2810              :          } else {
    2811            0 :             compose_name(pwd, param[1], str);
    2812              : 
    2813            0 :             status = db_find_link(hDB, 0, str, &hKey);
    2814            0 :             if (status == DB_SUCCESS) {
    2815            0 :                db_get_key(hDB, hKey, &key);
    2816            0 :                if (key.type != TID_KEY)
    2817            0 :                   printf("Watch key \"%s\" to be modified, abort with any key\n", str);
    2818              :                else
    2819            0 :                   printf("Watch ODB tree \"%s\" to be modified, abort with any key\n", str);
    2820            0 :                db_watch(hDB, hKey, watch_callback, NULL);
    2821              : 
    2822              :                do {
    2823            0 :                   status = cm_yield(1000);
    2824            0 :                   if (status == SS_ABORT || status == RPC_SHUTDOWN)
    2825              :                      break;
    2826            0 :                } while (!ss_kbhit());
    2827              : 
    2828            0 :                while (ss_kbhit())
    2829            0 :                   ss_getchar(0);
    2830              : 
    2831            0 :                db_unwatch(hDB, hKey);
    2832              : 
    2833            0 :                if (status == SS_ABORT || status == RPC_SHUTDOWN)
    2834              :                   break;
    2835              :             } else
    2836            0 :                printf("key \"%s\" not found\n", str);
    2837              :          }
    2838              :       }
    2839              : 
    2840              :       /* test 1  */
    2841            0 :       else if (param[0][0] == 't' && param[0][1] == '1') {
    2842              :          DWORD start_time;
    2843              :          INT i, size, rn;
    2844              :          HNDLE hKey;
    2845              : 
    2846            0 :          start_time = ss_millitime();
    2847            0 :          status = db_find_key(hDB, 0, "/runinfo/run number", &hKey);
    2848            0 :          assert(status == SUCCESS);
    2849            0 :          size = sizeof(rn);
    2850              : 
    2851            0 :          i = 0;
    2852              :          do {
    2853            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2854            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2855            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2856            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2857            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2858            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2859            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2860            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2861            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2862            0 :             db_get_data(hDB, hKey, &rn, &size, TID_INT);
    2863            0 :             i += 10;
    2864            0 :          } while (ss_millitime() - start_time < 5000);
    2865              : 
    2866            0 :          printf("%d accesses per second\n", i / 5);
    2867            0 :       }
    2868              : 
    2869              :       /* test 2 */
    2870            0 :       else if (param[0][0] == 't' && param[0][1] == '2') {
    2871              :          do {
    2872              :             do {
    2873            0 :                i = ss_getchar(0);
    2874            0 :                printf("%d\n", i);
    2875            0 :             } while (i > 0 && i != 4);
    2876              : 
    2877            0 :             ss_sleep(1000);
    2878            0 :          } while (i != 4);
    2879              : 
    2880            0 :          ss_getchar(1);
    2881              :       }
    2882              : 
    2883              :       /* test 3 */
    2884            0 :       else if (param[0][0] == 't' && param[0][1] == '3') {
    2885              : #ifdef USE_ADDRESS_SANITIZER
    2886              :          // test address sanitizer
    2887              :          int *a = (int *) malloc(sizeof(int) * 10);
    2888              :          i = a[11];
    2889              :          free(a);
    2890              : #else
    2891            0 :          printf("test address sanitizer is disabled!\n");
    2892              : #endif
    2893              :       }
    2894              : 
    2895              :       /* exit/quit */
    2896            0 :       else if ((param[0][0] == 'e' && param[0][1] == 'x' && param[0][2] == 'i') || (param[0][0] == 'q'))
    2897              :          break;
    2898              : 
    2899            0 :       else if (param[0][0] == 0)
    2900              :          ;
    2901              : 
    2902              :       else
    2903            0 :          printf("Unknown command %s %s %s\n", param[0], param[1], param[2]);
    2904              : 
    2905              :       /* exit after single command */
    2906            0 :       if (cmd_mode && cmd[0] != '@')
    2907            0 :          break;
    2908              : 
    2909              :       /* check if client connections are broken */
    2910            0 :       status = cm_yield(0);
    2911            0 :       if (status == SS_ABORT || status == RPC_SHUTDOWN)
    2912              :          break;
    2913              : 
    2914            0 :    } while (TRUE);
    2915              : 
    2916              :    /* check if client connections are broken */
    2917            0 :    status = cm_yield(0);
    2918              : 
    2919            0 :    return 1; /* indicate success */
    2920              : }
    2921              : 
    2922              : /*------------------------------------------------------------------*/
    2923              : 
    2924            0 : void ctrlc_odbedit(INT i) {
    2925              :    /* reset terminal */
    2926            0 :    ss_getchar(1);
    2927              : 
    2928              :    /* no shutdown message */
    2929            0 :    cm_set_msg_print(MT_ERROR, 0, NULL);
    2930              : 
    2931            0 :    cm_disconnect_experiment();
    2932              : 
    2933            0 :    printf("\n");
    2934            0 :    exit(EXIT_SUCCESS);
    2935              : }
    2936              : 
    2937              : /*------------------------------------------------------------------*/
    2938              : 
    2939              : #ifdef OS_VXWORKS
    2940              : int odbedit(char *ahost_name, char *aexp_name)
    2941              : #else
    2942            0 : int main(int argc, char *argv[])
    2943              : #endif
    2944              : {
    2945              :    INT status, i, odb_size, size;
    2946              :    char host_name[HOST_NAME_LENGTH], exp_name[NAME_LENGTH];
    2947              :    char cmd[2000], dir[256];
    2948              :    BOOL debug;
    2949              :    BOOL quiet;
    2950              :    BOOL corrupted;
    2951            0 :    BOOL reload_from_file = FALSE;
    2952              :    HNDLE hDB;
    2953              : 
    2954            0 :    cmd[0] = dir[0] = 0;
    2955            0 :    odb_size = DEFAULT_ODB_SIZE;
    2956            0 :    debug = corrupted = cmd_mode = quiet = FALSE;
    2957              : 
    2958              : #ifdef OS_VXWORKS
    2959              :    strcpy(host_name, ahost_name);
    2960              :    strcpy(exp_name, aexp_name);
    2961              : #else
    2962              : 
    2963              :    /* get default from environment */
    2964            0 :    cm_get_environment(host_name, sizeof(host_name), exp_name, sizeof(exp_name));
    2965              : 
    2966              :    /* check for MIDASSYS */
    2967            0 :    if (!getenv("MIDASSYS")) {
    2968            0 :       puts("Please define environment variable 'MIDASSYS'");
    2969            0 :       puts("pointing to the midas source installation directory.");
    2970              :    }
    2971              : 
    2972              :    /* parse command line parameters */
    2973            0 :    for (i = 1; i < argc; i++) {
    2974            0 :       if (argv[i][0] == '-' && argv[i][1] == 'g')
    2975            0 :          debug = TRUE;
    2976            0 :       else if (argv[i][0] == '-' && argv[i][1] == 'q')
    2977            0 :          quiet = TRUE;
    2978            0 :       else if (argv[i][0] == '-' && argv[i][1] == 'R')
    2979            0 :          reload_from_file = TRUE;
    2980            0 :       else if (argv[i][0] == '-' && argv[i][1] == 'C')
    2981            0 :          corrupted = TRUE;
    2982            0 :       else if (argv[i][0] == '-') {
    2983            0 :          if (i + 1 >= argc || argv[i + 1][0] == '-')
    2984            0 :             goto usage;
    2985            0 :          if (argv[i][1] == 'e')
    2986            0 :             strcpy(exp_name, argv[++i]);
    2987            0 :          else if (argv[i][1] == 'h')
    2988            0 :             strcpy(host_name, argv[++i]);
    2989            0 :          else if (argv[i][1] == 'c') {
    2990            0 :             if (strlen(argv[i + 1]) >= sizeof(cmd)) {
    2991            0 :                printf("error: command line too long (>%d bytes)\n", (int) sizeof(cmd));
    2992            0 :                return 0;
    2993              :             }
    2994            0 :             mstrlcpy(cmd, argv[++i], sizeof(cmd));
    2995            0 :             cmd_mode = TRUE;
    2996            0 :          } else if (argv[i][1] == 'd')
    2997            0 :             mstrlcpy(dir, argv[++i], sizeof(dir));
    2998            0 :          else if (argv[i][1] == 's')
    2999            0 :             odb_size = atoi(argv[++i]);
    3000              :          else {
    3001            0 :          usage:
    3002            0 :             printf("usage: odbedit [-h Hostname] [-e Experiment] [-d ODB Subtree]\n");
    3003            0 :             printf("               [-q] [-c Command] [-c @CommandFile] [-s size]\n");
    3004            0 :             printf("               [-g (debug)] [-C (connect to corrupted ODB)]\n");
    3005            0 :             printf("               [-R (reload ODB from .ODB.SHM)]\n\n");
    3006            0 :             printf("For a list of valid commands start odbedit interactively\n");
    3007            0 :             printf("and type \"help\".\n");
    3008            0 :             return 0;
    3009              :          }
    3010              :       } else
    3011            0 :          mstrlcpy(host_name, argv[i], sizeof(host_name));
    3012              :    }
    3013              : #endif
    3014              : 
    3015            0 :    if (reload_from_file) {
    3016              : #ifdef LOCAL_ROUTINES
    3017            0 :       status = cm_set_experiment_local(exp_name);
    3018            0 :       if (status != CM_SUCCESS) {
    3019            0 :          printf("Cannot setup experiment name and path.\n");
    3020            0 :          return 1;
    3021              :       }
    3022            0 :       status = ss_shm_delete("ODB");
    3023            0 :       printf("MIDAS ODB shared memory was deleted, ss_shm_delete(ODB) status %d\n", status);
    3024            0 :       printf("Please run odbedit again without \'-R\' and ODB will be reloaded from .ODB.SHM\n");
    3025            0 :       return 1;
    3026              : #else
    3027              :       printf("This odbedit only works remotely, -R is not supported\n");
    3028              :       return 1;
    3029              : #endif
    3030              :    }
    3031              : 
    3032              :    /* no startup message if called with command */
    3033            0 :    if (cmd[0])
    3034            0 :       cm_set_msg_print(MT_ERROR, 0, NULL);
    3035              : 
    3036            0 :    status = cm_connect_experiment1(host_name, exp_name, "ODBEdit", NULL,
    3037              :                                    odb_size, DEFAULT_WATCHDOG_TIMEOUT);
    3038              : 
    3039            0 :    if (host_name[0])
    3040            0 :       printf("Connected to MIDAS server \"%s\" experiment \"%s\"\n", host_name, exp_name);
    3041              : 
    3042            0 :    if (status == CM_WRONG_PASSWORD)
    3043            0 :       return 1;
    3044              : 
    3045            0 :    cm_msg_flush_buffer();
    3046              : 
    3047            0 :    if ((status == DB_INVALID_HANDLE) && corrupted) {
    3048            0 :       std::string s = cm_get_error(status);
    3049            0 :       puts(s.c_str());
    3050            0 :       printf("ODB is corrupted, connecting anyway...\n");
    3051            0 :    } else if (status != CM_SUCCESS) {
    3052            0 :       std::string s = cm_get_error(status);
    3053            0 :       puts(s.c_str());
    3054            0 :       return 1;
    3055            0 :    }
    3056              : 
    3057              :    /* place a request for system messages */
    3058            0 :    cm_msg_register(process_message);
    3059              : 
    3060              :    /* route local messages through print_message */
    3061            0 :    cm_set_msg_print(MT_ALL, MT_ALL, print_message);
    3062              : 
    3063              :    /* turn off watchdog if in debug mode */
    3064            0 :    if (debug)
    3065            0 :       cm_set_watchdog_params(FALSE, 0);
    3066              : 
    3067              :    /* get experiment name */
    3068            0 :    if (!exp_name[0]) {
    3069            0 :       cm_get_experiment_database(&hDB, NULL);
    3070            0 :       size = NAME_LENGTH;
    3071            0 :       db_get_value(hDB, 0, "/Experiment/Name", exp_name, &size, TID_STRING, TRUE);
    3072              :    }
    3073              : 
    3074              :    /* register Ctrl-C handler */
    3075            0 :    ss_ctrlc_handler(ctrlc_odbedit);
    3076              : 
    3077              :    /* for use with the mac os profiler */
    3078              :    //cmd_mode = TRUE;
    3079              :    //status = command_loop(host_name, exp_name, "save xxx3.json", dir);
    3080              : 
    3081              :    /* log all commands passed via -c on command line */
    3082            0 :    if (cmd_mode && !quiet)
    3083            0 :       cm_msg(MINFO, "odbedit", "Execute command from command line: \"%s\"", cmd);
    3084              : 
    3085              :    /* command loop */
    3086            0 :    status = command_loop(host_name, exp_name, cmd, dir);
    3087              : 
    3088              :    /* no shutdown message if called with command */
    3089            0 :    if (cmd_mode)
    3090            0 :       cm_set_msg_print(MT_ERROR, 0, NULL);
    3091              : 
    3092            0 :    cm_disconnect_experiment();
    3093              : 
    3094            0 :    if (status != 1)
    3095            0 :       return EXIT_FAILURE;
    3096              : 
    3097            0 :    return EXIT_SUCCESS;
    3098              : }
    3099              : 
    3100              : /* emacs
    3101              :  * Local Variables:
    3102              :  * tab-width: 8
    3103              :  * c-basic-offset: 3
    3104              :  * indent-tabs-mode: nil
    3105              :  * End:
    3106              :  */
        

Generated by: LCOV version 2.0-1