+ /* If choice not already made above, prompt */
+ for ( ; !done; ) {
+ char *fname;
+ int len;
+ bool gui_save;
+ db_list_ctx jobids;
+
+ start_prompt(ua, _("To select the JobIds, you have the following choices:\n"));
+ for (int i=0; list[i]; i++) {
+ add_prompt(ua, list[i]);
+ }
+ done = true;
+ switch (do_prompt(ua, "", _("Select item: "), NULL, 0)) {
+ case -1: /* error or cancel */
+ return 0;
+ case 0: /* list last 20 Jobs run */
+ if (!acl_access_ok(ua, Command_ACL, NT_("sqlquery"), 8)) {
+ ua->error_msg(_("SQL query not authorized.\n"));
+ return 0;
+ }
+ gui_save = ua->jcr->gui;
+ ua->jcr->gui = true;
+ db_list_sql_query(ua->jcr, ua->db, uar_list_jobs, prtit, ua, 1, HORZ_LIST);
+ ua->jcr->gui = gui_save;
+ done = false;
+ break;
+ case 1: /* list where a file is saved */
+ if (!get_client_name(ua, rx)) {
+ return 0;
+ }
+ if (!get_cmd(ua, _("Enter Filename (no path):"))) {
+ return 0;
+ }
+ len = strlen(ua->cmd);
+ fname = (char *)malloc(len * 2 + 1);
+ db_escape_string(ua->jcr, ua->db, fname, ua->cmd, len);
+ Mmsg(rx->query, uar_file[db_type], rx->ClientName, fname);
+ free(fname);
+ gui_save = ua->jcr->gui;
+ ua->jcr->gui = true;
+ db_list_sql_query(ua->jcr, ua->db, rx->query, prtit, ua, 1, HORZ_LIST);
+ ua->jcr->gui = gui_save;
+ done = false;
+ break;
+ case 2: /* enter a list of JobIds */
+ if (!get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) {
+ return 0;
+ }
+ pm_strcpy(rx->JobIds, ua->cmd);
+ break;
+ case 3: /* Enter an SQL list command */
+ if (!acl_access_ok(ua, Command_ACL, NT_("sqlquery"), 8)) {
+ ua->error_msg(_("SQL query not authorized.\n"));
+ return 0;
+ }
+ if (!get_cmd(ua, _("Enter SQL list command: "))) {
+ return 0;
+ }
+ gui_save = ua->jcr->gui;
+ ua->jcr->gui = true;
+ db_list_sql_query(ua->jcr, ua->db, ua->cmd, prtit, ua, 1, HORZ_LIST);
+ ua->jcr->gui = gui_save;
+ done = false;
+ break;
+ case 4: /* Select the most recent backups */
+ if (!have_date) {
+ bstrutime(date, sizeof(date), now);
+ }
+ if (!select_backups_before_date(ua, rx, date)) {
+ return 0;
+ }
+ break;
+ case 5: /* select backup at specified time */
+ if (!have_date) {
+ if (!get_date(ua, date, sizeof(date))) {
+ return 0;
+ }
+ }
+ if (!select_backups_before_date(ua, rx, date)) {
+ return 0;
+ }
+ break;
+ case 6: /* Enter files */
+ if (!have_date) {
+ bstrutime(date, sizeof(date), now);
+ }
+ if (!get_client_name(ua, rx)) {
+ return 0;
+ }
+ ua->send_msg(_("Enter file names with paths, or < to enter a filename\n"
+ "containing a list of file names with paths, and terminate\n"
+ "them with a blank line.\n"));
+ for ( ;; ) {
+ if (!get_cmd(ua, _("Enter full filename: "))) {
+ return 0;
+ }
+ len = strlen(ua->cmd);
+ if (len == 0) {
+ break;
+ }
+ insert_one_file_or_dir(ua, rx, date, false);
+ }
+ return 2;
+ case 7: /* enter files backed up before specified time */
+ if (!have_date) {
+ if (!get_date(ua, date, sizeof(date))) {
+ return 0;
+ }
+ }
+ if (!get_client_name(ua, rx)) {
+ return 0;
+ }
+ ua->send_msg(_("Enter file names with paths, or < to enter a filename\n"
+ "containing a list of file names with paths, and terminate\n"
+ "them with a blank line.\n"));
+ for ( ;; ) {
+ if (!get_cmd(ua, _("Enter full filename: "))) {
+ return 0;
+ }
+ len = strlen(ua->cmd);
+ if (len == 0) {
+ break;
+ }
+ insert_one_file_or_dir(ua, rx, date, false);
+ }
+ return 2;
+
+ case 8: /* Find JobIds for current backup */
+ if (!have_date) {
+ bstrutime(date, sizeof(date), now);
+ }
+ if (!select_backups_before_date(ua, rx, date)) {
+ return 0;
+ }
+ done = false;
+ break;
+
+ case 9: /* Find JobIds for give date */
+ if (!have_date) {
+ if (!get_date(ua, date, sizeof(date))) {
+ return 0;
+ }
+ }
+ if (!select_backups_before_date(ua, rx, date)) {
+ return 0;
+ }
+ done = false;
+ break;
+
+ case 10: /* Enter directories */
+ if (*rx->JobIds != 0) {
+ ua->send_msg(_("You have already selected the following JobIds: %s\n"),
+ rx->JobIds);
+ } else if (get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) {
+ if (*rx->JobIds != 0 && *ua->cmd) {
+ pm_strcat(rx->JobIds, ",");
+ }
+ pm_strcat(rx->JobIds, ua->cmd);
+ }
+ if (*rx->JobIds == 0 || *rx->JobIds == '.') {
+ return 0; /* nothing entered, return */
+ }
+ if (!have_date) {
+ bstrutime(date, sizeof(date), now);
+ }
+ if (!get_client_name(ua, rx)) {
+ return 0;
+ }
+ ua->send_msg(_("Enter full directory names or start the name\n"
+ "with a < to indicate it is a filename containing a list\n"
+ "of directories and terminate them with a blank line.\n"));
+ for ( ;; ) {
+ if (!get_cmd(ua, _("Enter directory name: "))) {
+ return 0;
+ }
+ len = strlen(ua->cmd);
+ if (len == 0) {
+ break;
+ }
+ /* Add trailing slash to end of directory names */
+ if (ua->cmd[0] != '<' && !IsPathSeparator(ua->cmd[len-1])) {
+ strcat(ua->cmd, "/");
+ }
+ insert_one_file_or_dir(ua, rx, date, true);
+ }
+ return 2;
+
+ case 11: /* Choose a jobid and select jobs */
+ if (!get_cmd(ua, _("Enter JobId to get the state to restore: ")) ||
+ !is_an_integer(ua->cmd))
+ {
+ return 0;
+ }
+
+ memset(&jr, 0, sizeof(JOB_DBR));
+ jr.JobId = str_to_int64(ua->cmd);
+ if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
+ ua->error_msg(_("Unable to get Job record for JobId=%s: ERR=%s\n"),
+ ua->cmd, db_strerror(ua->db));
+ return 0;
+ }
+ ua->send_msg(_("Selecting jobs to build the Full state at %s\n"),
+ jr.cStartTime);
+ jr.JobLevel = L_INCREMENTAL; /* Take Full+Diff+Incr */
+ if (!db_accurate_get_jobids(ua->jcr, ua->db, &jr, &jobids)) {
+ return 0;
+ }
+ pm_strcpy(rx->JobIds, jobids.list);
+ Dmsg1(30, "Item 12: jobids = %s\n", rx->JobIds);
+ break;
+ case 12: /* Cancel or quit */
+ return 0;