X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Futil.c;h=8a3e56453cb491e77b648bdc581bbe39db81ccfe;hb=4132c9f33642f579d89700f36caced609d374d51;hp=57fd42cd501f47cd5d7a6efd6a6541fc43bc0796;hpb=28346ad7fe97a74998f04157c8c63b39e4717ac8;p=bacula%2Fbacula diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 57fd42cd50..8a3e56453c 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -1,29 +1,36 @@ /* - * util.c miscellaneous utility subroutines for Bacula - * - * Kern Sibbald, MM - * - * Version $Id$ - */ + Bacula® - The Network Backup Solution -/* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2009 Free Software Foundation Europe e.V. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * util.c miscellaneous utility subroutines for Bacula + * + * Kern Sibbald, MM + * + * Version $Id$ */ #include "bacula.h" @@ -36,205 +43,74 @@ */ /* Return true of buffer has all zero bytes */ -int is_buf_zero(char *buf, int len) +bool is_buf_zero(char *buf, int len) { - uint64_t *ip = (uint64_t *)buf; + uint64_t *ip; char *p; int i, len64, done, rem; + if (buf[0] != 0) { + return false; + } + ip = (uint64_t *)buf; /* Optimize by checking uint64_t for zero */ - len64 = len >> sizeof(uint64_t); + len64 = len / sizeof(uint64_t); for (i=0; i < len64; i++) { if (ip[i] != 0) { - return 0; + return false; } } - done = len64 << sizeof(uint64_t); /* bytes already checked */ + done = len64 * sizeof(uint64_t); /* bytes already checked */ p = buf + done; rem = len - done; for (i = 0; i < rem; i++) { if (p[i] != 0) { - return 0; - } - } - return 1; -} - -/* - * Convert a string duration to utime_t (64 bit seconds) - * Returns 0: if error - 1: if OK, and value stored in value - */ -int duration_to_utime(char *str, utime_t *value) -{ - int i, ch, len; - double val; - static int mod[] = {'*', 's', 'n', 'h', 'd', 'w', 'm', 'q', 'y', 0}; - static int mult[] = {1, 1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30, - 60*60*24*91, 60*60*24*365}; - - /* Look for modifier */ - len = strlen(str); - ch = str[len - 1]; - i = 0; - if (B_ISALPHA(ch)) { - if (B_ISUPPER(ch)) { - ch = tolower(ch); + return false; } - while (mod[++i] != 0) { - if (ch == mod[i]) { - len--; - str[len] = 0; /* strip modifier */ - break; - } - } - } - if (mod[i] == 0 || !is_a_number(str)) { - return 0; } - val = strtod(str, NULL); - if (errno != 0 || val < 0) { - return 0; - } - *value = (utime_t)(val * mult[i]); - return 1; - + return true; } -/* - * Edit a utime "duration" into ASCII - */ -char *edit_utime(utime_t val, char *buf) -{ - char mybuf[30]; - static int mult[] = {60*60*24*365, 60*60*24*30, 60*60*24, 60*60, 60}; - static char *mod[] = {"year", "month", "day", "hour", "min"}; - int i; - uint32_t times; - - *buf = 0; - for (i=0; i<5; i++) { - times = val / mult[i]; - if (times > 0) { - val = val - (utime_t)times * mult[i]; - sprintf(mybuf, "%d %s%s ", times, mod[i], times>1?"s":""); - strcat(buf, mybuf); - } - } - if (val == 0 && strlen(buf) == 0) { - strcat(buf, "0 secs"); - } else if (val != 0) { - sprintf(mybuf, "%d sec%s", (uint32_t)val, val>1?"s":""); - strcat(buf, mybuf); - } - return buf; -} -/* - * Check if specified string is a number or not. - * Taken from SQLite, cool, thanks. - */ -int is_a_number(const char *n) +/* Convert a string in place to lower case */ +void lcase(char *str) { - int digit_seen = 0; - - if( *n == '-' || *n == '+' ) { - n++; - } - while (B_ISDIGIT(*n)) { - digit_seen = 1; - n++; - } - if (digit_seen && *n == '.') { - n++; - while (B_ISDIGIT(*n)) { n++; } - } - if (digit_seen && (*n == 'e' || *n == 'E') - && (B_ISDIGIT(n[1]) || ((n[1]=='-' || n[1] == '+') && B_ISDIGIT(n[2])))) { - n += 2; /* skip e- or e+ or e digit */ - while (B_ISDIGIT(*n)) { n++; } + while (*str) { + if (B_ISUPPER(*str)) { + *str = tolower((int)(*str)); + } + str++; } - return digit_seen && *n==0; } - -/* - * Edit an integer number with commas, the supplied buffer - * must be at least 27 bytes long. The incoming number - * is always widened to 64 bits. - */ -char *edit_uint64_with_commas(uint64_t val, char *buf) -{ - sprintf(buf, "%" lld, val); - return add_commas(buf, buf); -} - -/* - * Edit an integer number, the supplied buffer - * must be at least 27 bytes long. The incoming number - * is always widened to 64 bits. - */ -char *edit_uint64(uint64_t val, char *buf) -{ - sprintf(buf, "%" lld, val); - return buf; -} - - -/* - * Add commas to a string, which is presumably - * a number. +/* Convert spaces to non-space character. + * This makes scanf of fields containing spaces easier. */ -char *add_commas(char *val, char *buf) -{ - int len, nc; - char *p, *q; - int i; - - if (val != buf) { - strcpy(buf, val); - } - len = strlen(buf); - if (len < 1) { - len = 1; - } - nc = (len - 1) / 3; - p = buf+len; - q = p + nc; - *q-- = *p--; - for ( ; nc; nc--) { - for (i=0; i < 3; i++) { - *q-- = *p--; - } - *q-- = ','; - } - return buf; -} - - -/* Convert a string in place to lower case */ -void lcase(char *str) +void +bash_spaces(char *str) { while (*str) { - if (B_ISUPPER(*str)) - *str = tolower((int)(*str)); - str++; + if (*str == ' ') + *str = 0x1; + str++; } } -/* Convert spaces to non-space character. +/* Convert spaces to non-space character. * This makes scanf of fields containing spaces easier. */ void -bash_spaces(char *str) +bash_spaces(POOL_MEM &pm) { + char *str = pm.c_str(); while (*str) { if (*str == ' ') - *str = 0x1; + *str = 0x1; str++; } } + /* Convert non-space characters (0x1) back into spaces */ void unbash_spaces(char *str) @@ -246,180 +122,207 @@ unbash_spaces(char *str) } } -/* Strip any trailing junk from the command */ -void strip_trailing_junk(char *cmd) -{ - char *p; - p = cmd + strlen(cmd) - 1; - - /* strip trailing junk from command */ - while ((p >= cmd) && (*p == '\n' || *p == '\r' || *p == ' ')) - *p-- = 0; -} - -/* Strip any trailing slashes from a directory path */ -void strip_trailing_slashes(char *dir) -{ - char *p; - p = dir + strlen(dir) - 1; - - /* strip trailing slashes */ - while ((p >= dir) && (*p == '/')) - *p-- = 0; -} - -/* - * Skip spaces - * Returns: 0 on failure (EOF) - * 1 on success - * new address in passed parameter - */ -int skip_spaces(char **msg) +/* Convert non-space characters (0x1) back into spaces */ +void +unbash_spaces(POOL_MEM &pm) { - char *p = *msg; - if (!p) { - return 0; - } - while (*p && *p == ' ') { - p++; + char *str = pm.c_str(); + while (*str) { + if (*str == 0x1) + *str = ' '; + str++; } - *msg = p; - return *p ? 1 : 0; } -/* - * Skip nonspaces - * Returns: 0 on failure (EOF) - * 1 on success - * new address in passed parameter - */ -int skip_nonspaces(char **msg) +char *encode_time(utime_t utime, char *buf) { - char *p = *msg; + struct tm tm; + int n = 0; + time_t time = utime; - if (!p) { - return 0; - } - while (*p && *p != ' ') { - p++; - } - *msg = p; - return *p ? 1 : 0; -} +#if defined(HAVE_WIN32) + /* + * Avoid a seg fault in Microsoft's CRT localtime_r(), + * which incorrectly references a NULL returned from gmtime() if + * time is negative before or after the timezone adjustment. + */ + struct tm *gtm; -/* folded search for string - case insensitive */ -int -fstrsch(char *a, char *b) /* folded case search */ -{ - register char *s1,*s2; - register char c1, c2; - - s1=a; - s2=b; - while (*s1) { /* do it the fast way */ - if ((*s1++ | 0x20) != (*s2++ | 0x20)) - return 0; /* failed */ + if ((gtm = gmtime(&time)) == NULL) { + return buf; } - while (*a) { /* do it over the correct slow way */ - if (B_ISUPPER(c1 = *a)) { - c1 = tolower((int)c1); - } - if (B_ISUPPER(c2 = *b)) { - c2 = tolower((int)c2); - } - if (c1 != c2) { - return 0; - } - a++; - b++; - } - return 1; -} - -char *encode_time(time_t time, char *buf) -{ - struct tm tm; - int n = 0; + if (gtm->tm_year == 1970 && gtm->tm_mon == 1 && gtm->tm_mday < 3) { + return buf; + } +#endif if (localtime_r(&time, &tm)) { n = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); } return buf+n; } -/* - * Concatenate a string (str) onto a pool memory buffer pm - */ -void pm_strcat(POOLMEM **pm, char *str) -{ - int pmlen = strlen(*pm); - int len = strlen(str) + 1; - - *pm = check_pool_memory_size(*pm, pmlen + len); - memcpy(*pm+pmlen, str, len); -} /* - * Copy a string (str) into a pool memory buffer pm + * Convert a JobStatus code into a human readable form */ -void pm_strcpy(POOLMEM **pm, char *str) +void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) { - int len = strlen(str) + 1; + const char *jobstat; + char buf[100]; - *pm = check_pool_memory_size(*pm, len); - memcpy(*pm, str, len); -} + switch (JobStatus) { + case JS_Created: + jobstat = _("Created"); + break; + case JS_Running: + jobstat = _("Running"); + break; + case JS_Blocked: + jobstat = _("Blocked"); + break; + case JS_Terminated: + jobstat = _("OK"); + break; + case JS_FatalError: + case JS_ErrorTerminated: + jobstat = _("Error"); + break; + case JS_Error: + jobstat = _("Non-fatal error"); + break; + case JS_Warnings: + jobstat = _("OK -- with warnings"); + break; + case JS_Canceled: + jobstat = _("Canceled"); + break; + case JS_Differences: + jobstat = _("Verify differences"); + break; + case JS_WaitFD: + jobstat = _("Waiting on FD"); + break; + case JS_WaitSD: + jobstat = _("Wait on SD"); + break; + case JS_WaitMedia: + jobstat = _("Wait for new Volume"); + break; + case JS_WaitMount: + jobstat = _("Waiting for mount"); + break; + case JS_WaitStoreRes: + jobstat = _("Waiting for Storage resource"); + break; + case JS_WaitJobRes: + jobstat = _("Waiting for Job resource"); + break; + case JS_WaitClientRes: + jobstat = _("Waiting for Client resource"); + break; + case JS_WaitMaxJobs: + jobstat = _("Waiting on Max Jobs"); + break; + case JS_WaitStartTime: + jobstat = _("Waiting for Start Time"); + break; + case JS_WaitPriority: + jobstat = _("Waiting on Priority"); + break; + case JS_DataCommitting: + jobstat = _("SD committing Data"); + break; + case JS_DataDespooling: + jobstat = _("SD despooling Data"); + break; + case JS_AttrDespooling: + jobstat = _("SD despooling Attributes"); + break; + case JS_AttrInserting: + jobstat = _("Dir inserting Attributes"); + break; + default: + if (JobStatus == 0) { + buf[0] = 0; + } else { + bsnprintf(buf, sizeof(buf), _("Unknown Job termination status=%d"), JobStatus); + } + jobstat = buf; + break; + } + bstrncpy(msg, jobstat, maxlen); +} /* - * Convert a JobStatus code into a human readable form + * Convert a JobStatus code into a human readable form - gui version */ -void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) +void jobstatus_to_ascii_gui(int JobStatus, char *msg, int maxlen) { - char *termstat, jstat[2]; - + const char *cnv = NULL; switch (JobStatus) { - case JS_Terminated: - termstat = _("OK"); - break; - case JS_FatalError: - case JS_ErrorTerminated: - termstat = _("Error"); - break; - case JS_Error: - termstat = _("Non-fatal error"); - break; - case JS_Cancelled: - termstat = _("Cancelled"); - break; - case JS_Differences: - termstat = _("Verify differences"); - break; - default: - jstat[0] = last_job.JobStatus; - jstat[1] = 0; - termstat = jstat; - break; + case JS_Terminated: + cnv = _("Completed successfully"); + break; + case JS_Warnings: + cnv = _("Completed with warnings"); + break; + case JS_ErrorTerminated: + cnv = _("Terminated with errors"); + break; + case JS_FatalError: + cnv = _("Fatal error"); + break; + case JS_Created: + cnv = _("Created, not yet running"); + break; + case JS_Canceled: + cnv = _("Canceled by user"); + break; + case JS_Differences: + cnv = _("Verify found differences"); + break; + case JS_WaitFD: + cnv = _("Waiting for File daemon"); + break; + case JS_WaitSD: + cnv = _("Waiting for Storage daemon"); + break; + case JS_WaitPriority: + cnv = _("Waiting for higher priority jobs"); + break; + case JS_AttrInserting: + cnv = _("Batch inserting file records"); + break; + }; + + if (cnv) { + bstrncpy(msg, cnv, maxlen); + } else { + jobstatus_to_ascii(JobStatus, msg, maxlen); } - strncpy(msg, termstat, maxlen); - msg[maxlen-1] = 0; } + /* * Convert Job Termination Status into a string */ -char *job_status_to_str(int stat) +const char *job_status_to_str(int stat) { - char *str; + const char *str; switch (stat) { case JS_Terminated: str = _("OK"); break; + case JS_Warnings: + str = _("OK -- with warnings"); + break; case JS_ErrorTerminated: case JS_Error: str = _("Error"); @@ -427,8 +330,8 @@ char *job_status_to_str(int stat) case JS_FatalError: str = _("Fatal Error"); break; - case JS_Cancelled: - str = _("Cancelled"); + case JS_Canceled: + str = _("Canceled"); break; case JS_Differences: str = _("Differences"); @@ -444,38 +347,77 @@ char *job_status_to_str(int stat) /* * Convert Job Type into a string */ -char *job_type_to_str(int type) +const char *job_type_to_str(int type) { - char *str; + const char *str = NULL; switch (type) { case JT_BACKUP: str = _("Backup"); break; + case JT_MIGRATED_JOB: + str = _("Migrated Job"); + break; case JT_VERIFY: str = _("Verify"); break; case JT_RESTORE: str = _("Restore"); break; + case JT_CONSOLE: + str = _("Console"); + break; + case JT_SYSTEM: + str = _("System or Console"); + break; case JT_ADMIN: str = _("Admin"); break; - default: - str = _("Unknown Type"); + case JT_ARCHIVE: + str = _("Archive"); + break; + case JT_JOB_COPY: + str = _("Job Copy"); + break; + case JT_COPY: + str = _("Copy"); + break; + case JT_MIGRATE: + str = _("Migrate"); + break; + case JT_SCAN: + str = _("Scan"); break; } + if (!str) { + str = _("Unknown Type"); + } return str; } +/* Convert ActionOnPurge to string (Truncate, Erase, Destroy) + */ +char *action_on_purge_to_string(int aop, POOL_MEM &ret) +{ + if (aop & ON_PURGE_TRUNCATE) { + pm_strcpy(ret, _("Truncate")); + } + if (!aop) { + pm_strcpy(ret, _("None")); + } + return ret.c_str(); +} + /* * Convert Job Level into a string */ -char *job_level_to_str(int level) +const char *job_level_to_str(int level) { - char *str; + const char *str; switch (level) { + case L_BASE: + str = _("Base"); case L_FULL: str = _("Full"); break; @@ -485,9 +427,6 @@ char *job_level_to_str(int level) case L_DIFFERENTIAL: str = _("Differential"); break; - case L_LEVEL: - str = _("Level"); - break; case L_SINCE: str = _("Since"); break; @@ -500,9 +439,18 @@ char *job_level_to_str(int level) case L_VERIFY_VOLUME_TO_CATALOG: str = _("Verify Volume to Catalog"); break; + case L_VERIFY_DISK_TO_CATALOG: + str = _("Verify Disk to Catalog"); + break; case L_VERIFY_DATA: str = _("Verify Data"); break; + case L_VIRTUAL_FULL: + str = _("Virtual Full"); + break; + case L_NONE: + str = " "; + break; default: str = _("Unknown Job Level"); break; @@ -510,6 +458,33 @@ char *job_level_to_str(int level) return str; } +const char *volume_status_to_str(const char *status) +{ + int pos; + const char *vs[] = { + NT_("Append"), _("Append"), + NT_("Archive"), _("Archive"), + NT_("Disabled"), _("Disabled"), + NT_("Full"), _("Full"), + NT_("Used"), _("Used"), + NT_("Cleaning"), _("Cleaning"), + NT_("Purged"), _("Purged"), + NT_("Recycle"), _("Recycle"), + NT_("Read-Only"), _("Read-Only"), + NT_("Error"), _("Error"), + NULL, NULL}; + + if (status) { + for (pos = 0 ; vs[pos] ; pos += 2) { + if ( !strcmp(vs[pos],status) ) { + return vs[pos+1]; + } + } + } + + return _("Invalid volume status"); +} + /*********************************************************************** * Encode the mode bits into a 10 character string like LS does @@ -517,10 +492,10 @@ char *job_level_to_str(int level) char *encode_mode(mode_t mode, char *buf) { - char *cp = buf; + char *cp = buf; - *cp++ = S_ISDIR(mode) ? 'd' : S_ISBLK(mode) ? 'b' : S_ISCHR(mode) ? 'c' : - S_ISLNK(mode) ? 'l' : '-'; + *cp++ = S_ISDIR(mode) ? 'd' : S_ISBLK(mode) ? 'b' : S_ISCHR(mode) ? 'c' : + S_ISLNK(mode) ? 'l' : S_ISFIFO(mode) ? 'f' : S_ISSOCK(mode) ? 's' : '-'; *cp++ = mode & S_IRUSR ? 'r' : '-'; *cp++ = mode & S_IWUSR ? 'w' : '-'; *cp++ = (mode & S_ISUID @@ -540,325 +515,372 @@ char *encode_mode(mode_t mode, char *buf) return cp; } - -int do_shell_expansion(char *name) +#if defined(HAVE_WIN32) +int do_shell_expansion(char *name, int name_len) { -/* ****FIXME***** this should work for Win32 too */ -#define UNIX -#ifdef UNIX -#ifndef PATH_MAX -#define PATH_MAX 512 -#endif + char *src = bstrdup(name); - int pid, wpid, stat; - int waitstatus; - char *shellcmd; - void (*istat)(int), (*qstat)(int); - int i; - char echout[PATH_MAX + 256]; - int pfd[2]; + ExpandEnvironmentStrings(src, name, name_len); + + free(src); + + return 1; +} +#else +int do_shell_expansion(char *name, int name_len) +{ static char meta[] = "~\\$[]*?`'<>\""; - int found = FALSE; - int len; + bool found = false; + int len, i, stat; + POOLMEM *cmd; + BPIPE *bpipe; + char line[MAXSTRING]; + const char *shellcmd; /* Check if any meta characters are present */ len = strlen(meta); for (i = 0; i < len; i++) { if (strchr(name, meta[i])) { - found = TRUE; - break; + found = true; + break; } } - stat = 0; if (found) { -#ifdef nt - /* If the filename appears to be a DOS filename, - convert all backward slashes \ to Unix path - separators / and insert a \ infront of spaces. */ - len = strlen(name); - if (len >= 3 && name[1] == ':' && name[2] == '\\') { - for (i=2; i= 0) { - if (echout[i] == ' ' || echout[i] == '\n') - echout[i] = 0; /* keep only first one */ - } - istat = signal(SIGINT, SIG_IGN); - qstat = signal(SIGQUIT, SIG_IGN); - /* wait for child to exit */ - while ((wpid = wait(&waitstatus)) != pid && wpid != -1) - { ; } - signal(SIGINT, istat); - signal(SIGQUIT, qstat); - strcpy(name, echout); - stat = 1; - break; - } - close(pfd[0]); /* close pipe */ - close(pfd[1]); -#endif /* nt */ - } - return stat; - -#endif /* UNIX */ - -#if MSC | MSDOS | __WATCOMC__ - - char prefix[100], *env, *getenv(); - - /* Home directory reference? */ - if (*name == '~' && (env=getenv("HOME"))) { - strcpy(prefix, env); /* copy HOME directory name */ - name++; /* skip over ~ in name */ - strcat(prefix, name); - name--; /* get back to beginning */ - strcpy(name, prefix); /* move back into name */ + cmd = get_pool_memory(PM_FNAME); + /* look for shell */ + if ((shellcmd = getenv("SHELL")) == NULL) { + shellcmd = "/bin/sh"; + } + pm_strcpy(&cmd, shellcmd); + pm_strcat(&cmd, " -c \"echo "); + pm_strcat(&cmd, name); + pm_strcat(&cmd, "\""); + Dmsg1(400, "Send: %s\n", cmd); + if ((bpipe = open_bpipe(cmd, 0, "r"))) { + *line = 0; + fgets(line, sizeof(line), bpipe->rfd); + strip_trailing_junk(line); + stat = close_bpipe(bpipe); + Dmsg2(400, "stat=%d got: %s\n", stat, line); + } else { + stat = 1; /* error */ + } + free_pool_memory(cmd); + if (stat == 0) { + bstrncpy(name, line, name_len); + } } return 1; +} #endif -} -#define MAX_ARGV 100 -static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_arg); +/* MAKESESSIONKEY -- Generate session key with optional start + key. If mode is TRUE, the key will be + translated to a string, otherwise it is + returned as 16 binary bytes. -/* - * Run an external program. Optionally wait a specified number - * of seconds. Program killed if wait exceeded. Optionally - * return the output from the program (normally a single line). - */ -int run_program(char *prog, int wait, POOLMEM *results) + from SpeakFreely by John Walker */ + +void make_session_key(char *key, char *seed, int mode) { - int stat = ETIME; - int chldstatus = 0; - pid_t pid1, pid2 = 0; - int pfd[2]; - char *bargv[MAX_ARGV]; - int bargc; - - - build_argc_argv(prog, &bargc, bargv, MAX_ARGV); -#ifdef xxxxxxxxxx - printf("argc=%d\n", bargc); - int i; - for (i=0; i> 4) & 0xF); + key[k++] = Rad16(rb & 0xF); +#undef Rad16 + if (j & 1) { + key[k++] = '-'; + } + } + key[--k] = 0; + } else { + for (j = 0; j < 16; j++) { + key[j] = nextrand; + } } - /* Start worker process */ - switch (pid1 = fork()) { - case -1: - break; - - case 0: /* child */ -// printf("execl of %s\n", prog); - if (results) { - close(1); dup(pfd[1]); /* attach pipes to stdin and stdout */ - close(2); dup(pfd[1]); - } - execvp(bargv[0], bargv); - exit(errno); /* shouldn't get here */ - - default: /* parent */ - /* start timer process */ - if (wait > 0) { - switch (pid2=fork()) { - case -1: - break; - case 0: /* child 2 */ - /* Time the worker process */ - sleep(wait); - if (kill(pid1, SIGTERM) == 0) { /* time expired kill it */ - exit(0); - } - sleep(3); - kill(pid1, SIGKILL); - exit(0); - default: /* parent */ - break; - } - } +} +#undef nextrand - /* Parent continues here */ - int i; - if (results) { - i = read(pfd[0], results, sizeof_pool_memory(results) - 1); - if (--i < 0) { - i = 0; - } - results[i] = 0; /* set end of string */ - } - /* wait for worker child to exit */ - for ( ;; ) { - pid_t wpid; - wpid = waitpid(pid1, &chldstatus, 0); - if (wpid == pid1 || (errno != EINTR)) { - break; - } +void encode_session_key(char *encode, char *session, char *key, int maxlen) +{ + int i; + for (i=0; (i < maxlen-1) && session[i]; i++) { + if (session[i] == '-') { + encode[i] = '-'; + } else { + encode[i] = ((session[i] - 'A' + key[i]) & 0xF) + 'A'; } - if (WIFEXITED(chldstatus)) - stat = WEXITSTATUS(chldstatus); + } + encode[i] = 0; + Dmsg3(000, "Session=%s key=%s encode=%s\n", session, key, encode); +} - if (wait > 0) { - kill(pid2, SIGKILL); /* kill off timer process */ - waitpid(pid2, &chldstatus, 0); /* reap timer process */ - } - if (results) { - close(pfd[0]); /* close pipe */ - close(pfd[1]); +void decode_session_key(char *decode, char *session, char *key, int maxlen) +{ + int i, x; + + for (i=0; (i < maxlen-1) && session[i]; i++) { + if (session[i] == '-') { + decode[i] = '-'; + } else { + x = (session[i] - 'A' - key[i]) & 0xF; + if (x < 0) { + x += 16; + } + decode[i] = x + 'A'; } - break; } - return stat; + decode[i] = 0; + Dmsg3(000, "Session=%s key=%s decode=%s\n", session, key, decode); } + + /* - * Build argc and argv from a string + * Edit job codes into main command line + * %% = % + * %c = Client's name + * %d = Director's name + * %e = Job Exit code + * %i = JobId + * %j = Unique Job id + * %l = job level + * %n = Unadorned Job name + * %s = Since time + * %t = Job type (Backup, ...) + * %r = Recipients + * %v = Volume name + * %b = Job Bytes + * %f = Job Files + * + * omsg = edited output message + * imsg = input string containing edit codes (%x) + * to = recepients list + * */ -static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv) +POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_code_callback_t callback) { - int i, quote; char *p, *q; - int argc = 0; - - argc = 0; - for (i=0; iclient_name; + } else { + str = _("*none*"); + } + break; + case 'd': + str = my_name; /* Director's name */ + break; + case 'e': + if (jcr) { + str = job_status_to_str(jcr->JobStatus); + } else { + str = _("*none*"); + } + break; + case 'i': + if (jcr) { + bsnprintf(add, sizeof(add), "%d", jcr->JobId); + str = add; + } else { + str = _("*none*"); + } + break; + case 'j': /* Job name */ + if (jcr) { + str = jcr->Job; + } else { + str = _("*none*"); + } + break; + case 'l': + if (jcr) { + str = job_level_to_str(jcr->getJobLevel()); + } else { + str = _("*none*"); + } + break; + case 'n': + if (jcr) { + bstrncpy(name, jcr->Job, sizeof(name)); + /* There are three periods after the Job name */ + for (i=0; i<3; i++) { + if ((q=strrchr(name, '.')) != NULL) { + *q = 0; + } + } + str = name; + } else { + str = _("*none*"); + } + break; + case 'r': + str = to; + break; + case 's': /* since time */ + if (jcr && jcr->stime) { + str = jcr->stime; + } else { + str = _("*none*"); + } + break; + case 'f': /* Job Files */ + str = edit_uint64(jcr->JobFiles, add); + break; + case 'b': /* Job Bytes */ + str = edit_uint64(jcr->JobBytes, add); + break; + case 't': + if (jcr) { + str = job_type_to_str(jcr->getJobType()); + } else { + str = _("*none*"); + } + break; + case 'v': + if (jcr) { + if (jcr->VolumeName && jcr->VolumeName[0]) { + str = jcr->VolumeName; + } else { + str = ""; + } + } else { + str = _("*none*"); + } + break; + default: + str = NULL; + if (callback != NULL) { + str = callback(jcr, p); + } + + if (!str) { + add[0] = '%'; + add[1] = *p; + add[2] = 0; + str = add; + } + break; + } + } else { + add[0] = *p; + add[1] = 0; + str = add; } + Dmsg1(1200, "add_str %s\n", str); + pm_strcat(&omsg, str); + Dmsg1(1200, "omsg=%s\n", omsg); } - *bargc = argc; + return omsg; } -/* MAKESESSIONKEY -- Generate session key with optional start - key. If mode is TRUE, the key will be - translated to a string, otherwise it is - returned as 16 binary bytes. - - from SpeakFreely by John Walker */ - -void makeSessionKey(char *key, char *seed, int mode) +void set_working_directory(char *wd) { - int j, k; - struct MD5Context md5c; - unsigned char md5key[16], md5key1[16]; - char s[1024]; - - s[0] = 0; - if (seed != NULL) { - strcat(s, seed); - } + struct stat stat_buf; - /* The following creates a seed for the session key generator - based on a collection of volatile and environment-specific - information unlikely to be vulnerable (as a whole) to an - exhaustive search attack. If one of these items isn't - available on your machine, replace it with something - equivalent or, if you like, just delete it. */ - - sprintf(s + strlen(s), "%lu", (unsigned long) getpid()); - sprintf(s + strlen(s), "%lu", (unsigned long) getppid()); - getcwd(s + strlen(s), 256); - sprintf(s + strlen(s), "%lu", (unsigned long) clock()); - sprintf(s + strlen(s), "%lu", (unsigned long) time(NULL)); -#ifdef Solaris - sysinfo(SI_HW_SERIAL,s + strlen(s), 12); -#endif -#ifdef HAVE_GETHOSTID - sprintf(s + strlen(s), "%lu", (unsigned long) gethostid()); -#endif -#ifdef HAVE_GETDOMAINNAME - getdomainname(s + strlen(s), 256); -#endif - gethostname(s + strlen(s), 256); - sprintf(s + strlen(s), "%u", (unsigned)getuid()); - sprintf(s + strlen(s), "%u", (unsigned)getgid()); - MD5Init(&md5c); - MD5Update(&md5c, (unsigned char *)s, strlen(s)); - MD5Final(md5key, &md5c); - sprintf(s + strlen(s), "%lu", (unsigned long) ((time(NULL) + 65121) ^ 0x375F)); - MD5Init(&md5c); - MD5Update(&md5c, (unsigned char *)s, strlen(s)); - MD5Final(md5key1, &md5c); -#define nextrand (md5key[j] ^ md5key1[j]) - if (mode) { - for (j = k = 0; j < 16; j++) { - unsigned char rb = nextrand; + if (wd == NULL) { + Emsg0(M_ERROR_TERM, 0, _("Working directory not defined. Cannot continue.\n")); + } + if (stat(wd, &stat_buf) != 0) { + Emsg1(M_ERROR_TERM, 0, _("Working Directory: \"%s\" not found. Cannot continue.\n"), + wd); + } + if (!S_ISDIR(stat_buf.st_mode)) { + Emsg1(M_ERROR_TERM, 0, _("Working Directory: \"%s\" is not a directory. Cannot continue.\n"), + wd); + } + working_directory = wd; /* set global */ +} -#define Rad16(x) ((x) + 'A') - key[k++] = Rad16((rb >> 4) & 0xF); - key[k++] = Rad16(rb & 0xF); -#undef Rad16 - if (j & 1) { - key[k++] = '-'; - } - } - key[--k] = 0; - } else { - for (j = 0; j < 16; j++) { - key[j] = nextrand; - } - } +const char *last_path_separator(const char *str) +{ + if (*str != '\0') { + for (const char *p = &str[strlen(str) - 1]; p >= str; p--) { + if (IsPathSeparator(*p)) { + return p; + } + } + } + return NULL; } -#undef nextrand