- Figure out how to use ssh or stunnel to protect Bacula communications.
For 1.31 release:
+- Use switch() in backup.c and restore.c in FD instead of giant if statement.
- Investigate doing RAW backup of Win32 partition.
- Add JobName= to VerifyToCatalog so that all verifies can be done at the end.
- Add thread specific data to hold the jcr -- send error messages from
- Put system type returned by FD into catalog.
- Finish WIN32_DATA stream code (bextract, check if can handle stream)
- Make SD keep track of Files, Bytes during restore.
-
static char OKbackup[] = "2000 OK backup\n";
static char OKstore[] = "2000 OK storage\n";
static char OKlevel[] = "2000 OK level\n";
-static char EndBackup[] = "2801 End Backup Job TermCode=%d JobFiles=%u ReadBytes=%" lld " JobBytes=%" lld " Errors=%u\n";
+static char EndBackup[] = "2801 End Backup Job TermCode=%d JobFiles=%u "
+ "ReadBytes=%" lld " JobBytes=%" lld " Errors=%u\n";
/* Forward referenced functions */
fd_ok = TRUE;
set_jcr_job_status(jcr, jcr->FDJobStatus);
Dmsg1(100, "FDStatus=%c\n", (char)jcr->JobStatus);
+ } else {
+ Jmsg(jcr, M_WARNING, 0, _("Unexpected Client Job message: %s\n"),
+ fd->msg);
}
if (job_canceled(jcr)) {
break;
}
/* Now update the bootstrap file if any */
- if (jcr->JobStatus == JS_Terminated && jcr->jr.JobBytes &&jcr->job->WriteBootstrap) {
+ if (jcr->JobStatus == JS_Terminated && jcr->jr.JobBytes &&
+ jcr->job->WriteBootstrap) {
FILE *fd;
BPIPE *bpipe = NULL;
int got_pipe = 0;
}
/* Reset globals */
- working_directory = director->working_directory;
+ set_working_directory(director->working_directory);
FDConnectTimeout = director->FDConnectTimeout;
SDConnectTimeout = director->SDConnectTimeout;
Without that I don't know who I am :-(\n"), configfile);
OK = FALSE;
} else {
- if (!director->working_directory) {
- Jmsg(NULL, M_FATAL, 0, _("No working directory specified. Cannot continue.\n"));
- OK = FALSE;
- }
- working_directory = director->working_directory;
+ set_working_directory(director->working_directory);
if (!director->messages) { /* If message resource not specified */
director->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
if (!director->messages) {
close_msg(NULL); /* close temp message handler */
init_msg(NULL, me->messages); /* open user specified message handler */
}
- working_directory = me->working_directory;
+
+ set_working_directory(me->working_directory);
if (test_config) {
terminate_filed(0);
if (sd == NULL) {
Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
- set_jcr_job_status(jcr, JS_ErrorTerminated);
goto cleanup;
}
Dmsg1(110, "<stored: %s", sd->msg);
if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
- set_jcr_job_status(jcr, JS_ErrorTerminated);
goto cleanup;
}
Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
} else {
Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
- set_jcr_job_status(jcr, JS_ErrorTerminated);
goto cleanup;
}
*/
Dmsg1(110, "<stored: %s", sd->msg);
if (!response(jcr, sd, OK_data, "Append Data")) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
goto cleanup;
}
}
if (!ok) {
Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
- set_jcr_job_status(jcr, JS_ErrorTerminated);
goto cleanup;
}
if (SDJobStatus != JS_Terminated) {
Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
SDJobStatus);
- set_jcr_job_status(jcr, JS_ErrorTerminated);
}
}
break;
case FT_NOACCESS:
Jmsg(jcr, M_NOTSAVED, -1, _(" Could not access %s: ERR=%s\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
+ jcr->Errors++;
return 1;
case FT_NOFOLLOW:
Jmsg(jcr, M_NOTSAVED, -1, _(" Could not follow link %s: ERR=%s\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
+ jcr->Errors++;
return 1;
case FT_NOSTAT:
Jmsg(jcr, M_NOTSAVED, -1, _(" Could not stat %s: ERR=%s\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
+ jcr->Errors++;
return 1;
case FT_DIRNOCHG:
case FT_NOCHG:
return 1;
case FT_NOOPEN:
Jmsg(jcr, M_NOTSAVED, -1, _(" Could not open directory %s: ERR=%s\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
+ jcr->Errors++;
return 1;
default:
Jmsg(jcr, M_NOTSAVED, 0, _(" Unknown file type %d: %s\n"), ff_pkt->type, ff_pkt->fname);
+ jcr->Errors++;
return 1;
}
ff_pkt->ff_errno = errno;
Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open %s: ERR=%s.\n"),
ff_pkt->fname, berror(&bfd));
+ jcr->Errors++;
return 1;
}
}
jcr->JobBytes += n;
}
if (n < 0) {
- Jmsg(jcr, M_WARNING, -1, _("Error reading file %s: ERR=%s\n"),
+ Jmsg(jcr, M_ERROR, -1, _("Error reading file %s: ERR=%s\n"),
ff_pkt->fname, berror(&bfd));
}
MD5Final(signature, &md5c);
jcr->JobBytes += n;
}
if (n < 0) {
- Jmsg(jcr, M_WARNING, -1, _("Error reading file %s: ERR=%s\n"),
+ Jmsg(jcr, M_ERROR, -1, _("Error reading file %s: ERR=%s\n"),
ff_pkt->fname, berror(&bfd));
}
SHA1Final(&sha1c, signature);
Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
/* File Attributes stream */
- if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) {
+ switch (stream) {
+ case STREAM_UNIX_ATTRIBUTES:
+ case STREAM_WIN32_ATTRIBUTES:
char *ap, *lp, *fp;
Dmsg0(400, "Stream=Unix Attributes.\n");
Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
goto bail_out;
}
+ break;
-
- /* Data stream */
- } else if (stream == STREAM_FILE_DATA || stream == STREAM_SPARSE_DATA) {
-
- /* Do nothing */
-
- /* GZIP data stream */
- } else if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
-
- /* Do nothing */
-
- } else if (stream == STREAM_WIN32_DATA || stream == STREAM_WIN32_GZIP_DATA) {
+ /* Data streams to ignore */
+ case STREAM_FILE_DATA:
+ case STREAM_SPARSE_DATA:
+ case STREAM_WIN32_DATA:
+ case STREAM_WIN32_GZIP_DATA:
+ case STREAM_GZIP_DATA:
+ case STREAM_SPARSE_GZIP_DATA:
/* Do nothing */
+ break;
- /* If MD5 stream */
- } else if (stream == STREAM_MD5_SIGNATURE) {
+ case STREAM_MD5_SIGNATURE:
char MD5buf[30];
bin_to_base64(MD5buf, (char *)sd->msg, 16); /* encode 16 bytes */
Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, MD5buf);
bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_SIGNATURE, MD5buf,
jcr->JobFiles);
Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
+ break;
- /* If SHA1 stream */
- } else if (stream == STREAM_SHA1_SIGNATURE) {
+ case STREAM_SHA1_SIGNATURE:
char SHA1buf[30];
bin_to_base64(SHA1buf, (char *)sd->msg, 20); /* encode 20 bytes */
Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, SHA1buf);
bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_SIGNATURE,
SHA1buf, jcr->JobFiles);
Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
- } else {
+ break;
+
+ default:
Pmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg);
- }
- }
+ break;
+ } /* end switch */
+ } /* end while bnet_get */
set_jcr_job_status(jcr, JS_Terminated);
goto ok_out;
bail_out:
set_jcr_job_status(jcr, JS_ErrorTerminated);
+
ok_out:
if (jcr->compress_buf) {
free(jcr->compress_buf);
first_rule: all
dummy:
-LIBSRCS = alloc.c base64.c bmisc.c bget_msg.c \
+LIBSRCS = alloc.c base64.c bsys.c bget_msg.c \
bnet.c bnet_server.c \
bpipe.c bshm.c btime.c \
cram-md5.c crc32.c daemon.c edit.c fnmatch.c \
# immortal.c filesys.c
-LIBOBJS = alloc.o base64.o bmisc.o bget_msg.o \
+LIBOBJS = alloc.o base64.o bsys.o bget_msg.o \
bnet.o bnet_server.o \
bpipe.o bshm.o btime.o \
cram-md5.o crc32.o daemon.o edit.o fnmatch.o \
--- /dev/null
+/*
+ * Miscellaneous Bacula memory and thread safe routines
+ * Generally, these are interfaces to system or standard
+ * library routines.
+ *
+ * Bacula utility functions are in util.c
+ *
+ * Version $Id$
+ */
+/*
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+ 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.
+
+ 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.
+
+ */
+
+
+#include "bacula.h"
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
+/*
+ * Guarantee that the string is properly terminated */
+char *bstrncpy(char *dest, const char *src, int maxlen)
+{
+ strncpy(dest, src, maxlen-1);
+ dest[maxlen-1] = 0;
+ return dest;
+}
+
+char *bstrncat(char *dest, const char *src, int maxlen)
+{
+ strncat(dest, src, maxlen-1);
+ dest[maxlen-1] = 0;
+ return dest;
+}
+
+
+#ifndef DEBUG
+void *bmalloc(size_t size)
+{
+ void *buf;
+
+ buf = malloc(size);
+ if (buf == NULL) {
+ Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), strerror(errno));
+ }
+ return buf;
+}
+#endif
+
+void *b_malloc(char *file, int line, size_t size)
+{
+ void *buf;
+
+#ifdef SMARTALLOC
+ buf = sm_malloc(file, line, size);
+#else
+ buf = malloc(size);
+#endif
+ if (buf == NULL) {
+ e_msg(file, line, M_ABORT, 0, _("Out of memory: ERR=%s\n"), strerror(errno));
+ }
+ return buf;
+}
+
+
+void *brealloc (void *buf, size_t size)
+{
+ buf = realloc(buf, size);
+ if (buf == NULL) {
+ Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), strerror(errno));
+ }
+ return buf;
+}
+
+
+void *bcalloc (size_t size1, size_t size2)
+{
+ void *buf;
+
+ buf = calloc(size1, size2);
+ if (buf == NULL) {
+ Emsg1(M_ABORT, 0, _("Out of memory: ERR=%s\n"), strerror(errno));
+ }
+ return buf;
+}
+
+
+#define BIG_BUF 5000
+/*
+ * Implement snprintf
+ */
+int bsnprintf(char *str, size_t size, const char *fmt, ...)
+{
+#ifdef HAVE_VSNPRINTF
+ va_list arg_ptr;
+ int len;
+
+ va_start(arg_ptr, fmt);
+ len = vsnprintf(str, size, fmt, arg_ptr);
+ va_end(arg_ptr);
+ str[size-1] = 0;
+ return len;
+
+#else
+
+ va_list arg_ptr;
+ int len;
+ char *buf;
+
+ buf = get_memory(BIG_BUF);
+ va_start(arg_ptr, fmt);
+ len = vsprintf(buf, fmt, arg_ptr);
+ va_end(arg_ptr);
+ if (len >= BIG_BUF) {
+ Emsg0(M_ABORT, 0, _("Buffer overflow.\n"));
+ }
+ memcpy(str, buf, size);
+ str[size-1] = 0;
+ free_memory(buf);
+ return len;
+#endif
+}
+
+/*
+ * Implement vsnprintf()
+ */
+int bvsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+#ifdef HAVE_VSNPRINTF
+ int len;
+ len = vsnprintf(str, size, format, ap);
+ str[size-1] = 0;
+ return len;
+
+#else
+
+ int len;
+ char *buf;
+ buf = get_memory(BIG_BUF);
+ len = vsprintf(buf, format, ap);
+ if (len >= BIG_BUF) {
+ Emsg0(M_ABORT, 0, _("Buffer overflow.\n"));
+ }
+ memcpy(str, buf, size);
+ str[size-1] = 0;
+ free_memory(buf);
+ return len;
+#endif
+}
+
+#ifndef HAVE_LOCALTIME_R
+
+struct tm *localtime_r(const time_t *timep, struct tm *tm)
+{
+ static pthread_mutex_t mutex;
+ static int first = 1;
+ struct tm *ltm;
+
+ if (first) {
+ pthread_mutex_init(&mutex, NULL);
+ first = 0;
+ }
+ P(mutex);
+ ltm = localtime(timep);
+ if (ltm) {
+ memcpy(tm, ltm, sizeof(struct tm));
+ }
+ V(mutex);
+ return ltm ? tm : NULL;
+}
+#endif /* HAVE_LOCALTIME_R */
+
+#ifndef HAVE_READDIR_R
+
+#include <dirent.h>
+
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
+{
+ static pthread_mutex_t mutex;
+ static int first = 1;
+ struct dirent *ndir;
+ int stat;
+
+ if (first) {
+ pthread_mutex_init(&mutex, NULL);
+ first = 0;
+ }
+ P(mutex);
+ errno = 0;
+ ndir = readdir(dirp);
+ stat = errno;
+ if (ndir) {
+ memcpy(entry, ndir, sizeof(struct dirent));
+ strcpy(entry->d_name, ndir->d_name);
+ *result = entry;
+ } else {
+ *result = NULL;
+ }
+ V(mutex);
+ return stat;
+}
+
+#endif /* HAVE_READDIR_R */
+
+#ifdef xxxxxxxxxx_STRERROR_R
+int strerror_r(int errnum, char *buf, size_t bufsiz)
+{
+ static pthread_mutex_t mutex;
+ static int first = 1;
+ int stat = 0;
+ char *msg;
+
+ if (first) {
+ pthread_mutex_init(&mutex, NULL);
+ first = 0;
+ }
+ P(mutex);
+
+ msg = strerror(errnum);
+ if (!msg) {
+ msg = _("Bad errno");
+ stat = -1;
+ }
+ bstrncpy(buf, msg, bufsiz);
+ V(mutex);
+ return stat;
+}
+#endif /* HAVE_STRERROR_R */
+
+/*
+ * These are mutex routines that do error checking
+ * for deadlock and such. Normally not turned on.
+ */
+#ifdef DEBUG_MUTEX
+void _p(char *file, int line, pthread_mutex_t *m)
+{
+ int errstat;
+ if ((errstat = pthread_mutex_trylock(m))) {
+ e_msg(file, line, M_ERROR, 0, _("Possible mutex deadlock.\n"));
+ /* We didn't get the lock, so do it definitely now */
+ if ((errstat=pthread_mutex_lock(m))) {
+ e_msg(file, line, M_ABORT, 0, _("Mutex lock failure. ERR=%s\n"),
+ strerror(errstat));
+ } else {
+ e_msg(file, line, M_ERROR, 0, _("Possible mutex deadlock resolved.\n"));
+ }
+
+ }
+}
+
+void _v(char *file, int line, pthread_mutex_t *m)
+{
+ int errstat;
+
+ if ((errstat=pthread_mutex_trylock(m)) == 0) {
+ e_msg(file, line, M_ERROR, 0, _("Mutex unlock not locked. ERR=%s\n"),
+ strerror(errstat));
+ }
+ if ((errstat=pthread_mutex_unlock(m))) {
+ e_msg(file, line, M_ABORT, 0, _("Mutex unlock failure. ERR=%s\n"),
+ strerror(errstat));
+ }
+}
+#endif /* DEBUG_MUTEX */
+
+#ifndef HAVE_CYGWIN
+static int del_pid_file_ok = FALSE;
+#endif
+
+/*
+ * Create a standard "Unix" pid file.
+ */
+void create_pid_file(char *dir, char *progname, int port)
+{
+#ifndef HAVE_CYGWIN
+ int pidfd, len;
+ int oldpid;
+ char pidbuf[20];
+ POOLMEM *fname = get_pool_memory(PM_FNAME);
+ struct stat statp;
+
+ Mmsg(&fname, "%s/%s.%d.pid", dir, progname, port);
+ if (stat(fname, &statp) == 0) {
+ /* File exists, see what we have */
+ *pidbuf = 0;
+ if ((pidfd = open(fname, O_RDONLY)) < 0 ||
+ read(pidfd, &pidbuf, sizeof(pidbuf)) < 0 ||
+ sscanf(pidbuf, "%d", &oldpid) != 1) {
+ Emsg2(M_ERROR_TERM, 0, _("Cannot open pid file. %s ERR=%s\n"), fname, strerror(errno));
+ }
+ /* See if other Bacula is still alive */
+ if (kill(oldpid, 0) != -1 || errno != ESRCH) {
+ Emsg3(M_ERROR_TERM, 0, _("%s is already running. pid=%d\nCheck file %s\n"),
+ progname, oldpid, fname);
+ }
+ /* He is not alive, so take over file ownership */
+ unlink(fname); /* remove stale pid file */
+ }
+ /* Create new pid file */
+ if ((pidfd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0644)) >= 0) {
+ len = sprintf(pidbuf, "%d\n", (int)getpid());
+ write(pidfd, pidbuf, len);
+ close(pidfd);
+ del_pid_file_ok = TRUE; /* we created it so we can delete it */
+ } else {
+ Emsg2(M_ERROR_TERM, 0, _("Could not open pid file. %s ERR=%s\n"), fname, strerror(errno));
+ }
+ free_pool_memory(fname);
+#endif
+}
+
+/*
+ * Delete the pid file if we created it
+ */
+int delete_pid_file(char *dir, char *progname, int port)
+{
+#ifndef HAVE_CYGWIN
+ POOLMEM *fname = get_pool_memory(PM_FNAME);
+
+ if (!del_pid_file_ok) {
+ free_pool_memory(fname);
+ return 0;
+ }
+ del_pid_file_ok = FALSE;
+ Mmsg(&fname, "%s/%s.%d.pid", dir, progname, port);
+ unlink(fname);
+ free_pool_memory(fname);
+#endif
+ return 1;
+}
+
+/*
+ * Drop to privilege new userid and new gid if non-NULL
+ */
+void drop(char *uid, char *gid)
+{
+#ifdef HAVE_GRP_H
+ if (gid) {
+ struct group *group;
+ gid_t gr_list[1];
+
+ if ((group = getgrnam(gid)) == NULL) {
+ Emsg1(M_ERROR_TERM, 0, _("Could not find specified group: %s\n"), gid);
+ }
+ if (setgid(group->gr_gid)) {
+ Emsg1(M_ERROR_TERM, 0, _("Could not set specified group: %s\n"), gid);
+ }
+ gr_list[0] = group->gr_gid;
+ if (setgroups(1, gr_list)) {
+ Emsg1(M_ERROR_TERM, 0, _("Could not set specified group: %s\n"), gid);
+ }
+ }
+#endif
+
+#ifdef HAVE_PWD_H
+ if (uid) {
+ struct passwd *passw;
+ if ((passw = getpwnam(uid)) == NULL) {
+ Emsg1(M_ERROR_TERM, 0, _("Could not find specified userid: %s\n"), uid);
+ }
+ if (setuid(passw->pw_uid)) {
+ Emsg1(M_ERROR_TERM, 0, _("Could not set specified userid: %s\n"), uid);
+ }
+ }
+#endif
+
+}
+
+static pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t timer = PTHREAD_COND_INITIALIZER;
+
+/*
+ * This routine will sleep (sec, msec). Note, however, that if a
+ * signal occurs, it will return early. It is up to the caller
+ * to recall this routine if he/she REALLY wants to sleep the
+ * requested time.
+ */
+int bmicrosleep(time_t sec, long msec)
+{
+ struct timespec timeout;
+ struct timeval tv;
+ struct timezone tz;
+ int stat;
+
+ timeout.tv_sec = sec;
+ timeout.tv_nsec = msec * 1000;
+
+#ifdef HAVE_NANOSLEEP
+ stat = nanosleep(&timeout, NULL);
+ if (!(stat < 0 && errno == ENOSYS)) {
+ return stat;
+ }
+ /* If we reach here it is because nanosleep is not supported by the OS */
+#endif
+
+ /* Do it the old way */
+ gettimeofday(&tv, &tz);
+ timeout.tv_nsec += tv.tv_usec * 1000;
+ timeout.tv_sec += tv.tv_sec;
+ while (timeout.tv_nsec >= 1000000000) {
+ timeout.tv_nsec -= 1000000000;
+ timeout.tv_sec++;
+ }
+
+ Dmsg1(200, "pthread_cond_timedwait sec=%d\n", timeout.tv_sec);
+ /* Note, this unlocks mutex during the sleep */
+ P(timer_mutex);
+ stat = pthread_cond_timedwait(&timer, &timer_mutex, &timeout);
+ Dmsg1(200, "pthread_cond_timedwait stat=%d\n", stat);
+ V(timer_mutex);
+ return stat;
+}
+
+/* BSDI does not have this. This is a *poor* simulation */
+#ifndef HAVE_STRTOLL
+long long int
+strtoll(const char *ptr, char **endptr, int base)
+{
+ return (long long int)strtod(ptr, endptr);
+}
+#endif
len = sprintf(rbuf, "%s: %s Fatal error: ", my_name, job);
if (jcr) {
set_jcr_job_status(jcr, JS_FatalError);
- jcr->Errors++;
}
break;
case M_ERROR:
lex_get_token(lc, T_STRING);
if (pass == 1) {
if (lc->str[0] != '|') {
- do_shell_expansion(lc->str);
+ do_shell_expansion(lc->str, sizeof(lc->str));
}
*(item->value) = bstrdup(lc->str);
}
*/
/* base64.c */
-void base64_init (void);
-int to_base64 (intmax_t value, char *where);
-int from_base64 (intmax_t *value, char *where);
-int bin_to_base64 (char *buf, char *bin, int len);
+void base64_init (void);
+int to_base64 (intmax_t value, char *where);
+int from_base64 (intmax_t *value, char *where);
+int bin_to_base64 (char *buf, char *bin, int len);
/* bmisc.c */
-char *bstrncpy (char *dest, const char *src, int maxlen);
-char *bstrncat (char *dest, const char *src, int maxlen);
-void *b_malloc (char *file, int line, size_t size);
+char *bstrncpy (char *dest, const char *src, int maxlen);
+char *bstrncat (char *dest, const char *src, int maxlen);
+void *b_malloc (char *file, int line, size_t size);
#ifndef DEBUG
-void *bmalloc (size_t size);
+void *bmalloc (size_t size);
#endif
-void *brealloc (void *buf, size_t size);
-void *bcalloc (size_t size1, size_t size2);
-int bsnprintf (char *str, size_t size, const char *format, ...);
-int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
-int pool_sprintf (char *pool_buf, char *fmt, ...);
-void create_pid_file (char *dir, char *progname, int port);
-int delete_pid_file (char *dir, char *progname, int port);
-void drop (char *uid, char *gid);
-int bmicrosleep (time_t sec, long msec);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, size_t size, const char *format, ...);
+int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
+int pool_sprintf (char *pool_buf, char *fmt, ...);
+void create_pid_file (char *dir, char *progname, int port);
+int delete_pid_file (char *dir, char *progname, int port);
+void drop (char *uid, char *gid);
+int bmicrosleep (time_t sec, long msec);
#ifndef HAVE_STRTOLL
long long int strtoll(const char *ptr, char **endptr, int base);
#endif
/* bnet.c */
-int32_t bnet_recv (BSOCK *bsock);
-int bnet_send (BSOCK *bsock);
-int bnet_fsend (BSOCK *bs, char *fmt, ...);
-int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-int bnet_sig (BSOCK *bs, int sig);
-int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
-int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need);
-BSOCK * bnet_connect (void *jcr, int retry_interval,
- int max_retry_time, char *name, char *host, char *service,
- int port, int verbose);
-void bnet_close (BSOCK *bsock);
-BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port);
-BSOCK * dup_bsock (BSOCK *bsock);
-void term_bsock (BSOCK *bsock);
-char * bnet_strerror (BSOCK *bsock);
-char * bnet_sig_to_ascii (BSOCK *bsock);
-int bnet_wait_data (BSOCK *bsock, int sec);
-int bnet_wait_data_intr (BSOCK *bsock, int sec);
-int bnet_despool (BSOCK *bsock);
-int is_bnet_stop (BSOCK *bsock);
-int is_bnet_error (BSOCK *bsock);
-void bnet_suppress_error_messages(BSOCK *bsock, int flag);
+int32_t bnet_recv (BSOCK *bsock);
+int bnet_send (BSOCK *bsock);
+int bnet_fsend (BSOCK *bs, char *fmt, ...);
+int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+int bnet_sig (BSOCK *bs, int sig);
+int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
+int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need);
+BSOCK * bnet_connect (void *jcr, int retry_interval,
+ int max_retry_time, char *name, char *host, char *service,
+ int port, int verbose);
+void bnet_close (BSOCK *bsock);
+BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port);
+BSOCK * dup_bsock (BSOCK *bsock);
+void term_bsock (BSOCK *bsock);
+char * bnet_strerror (BSOCK *bsock);
+char * bnet_sig_to_ascii (BSOCK *bsock);
+int bnet_wait_data (BSOCK *bsock, int sec);
+int bnet_wait_data_intr (BSOCK *bsock, int sec);
+int bnet_despool (BSOCK *bsock);
+int is_bnet_stop (BSOCK *bsock);
+int is_bnet_error (BSOCK *bsock);
+void bnet_suppress_error_messages(BSOCK *bsock, int flag);
/* bget_msg.c */
-int bget_msg(BSOCK *sock);
+int bget_msg(BSOCK *sock);
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need);
int cram_md5_auth(BSOCK *bs, char *password, int ssl_need);
void hmac_md5(uint8_t* text, int text_len, uint8_t* key,
- int key_len, uint8_t *hmac);
+ int key_len, uint8_t *hmac);
/* crc32.c */
uint32_t bcrc32(uint8_t *buf, int len);
/* daemon.c */
-void daemon_start ();
+void daemon_start ();
/* edit.c */
-uint64_t str_to_uint64(char *str);
-int64_t str_to_int64(char *str);
-char * edit_uint64_with_commas (uint64_t val, char *buf);
-char * add_commas (char *val, char *buf);
-char * edit_uint64 (uint64_t val, char *buf);
-int duration_to_utime (char *str, utime_t *value);
-int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
-char *edit_utime (utime_t val, char *buf);
-int is_a_number (const char *num);
-int is_an_integer (const char *n);
+uint64_t str_to_uint64(char *str);
+int64_t str_to_int64(char *str);
+char * edit_uint64_with_commas (uint64_t val, char *buf);
+char * add_commas (char *val, char *buf);
+char * edit_uint64 (uint64_t val, char *buf);
+int duration_to_utime (char *str, utime_t *value);
+int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
+char *edit_utime (utime_t val, char *buf);
+int is_a_number (const char *num);
+int is_an_integer (const char *n);
/* lex.c */
-LEX * lex_close_file (LEX *lf);
-LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
-int lex_get_char (LEX *lf);
-void lex_unget_char (LEX *lf);
-char * lex_tok_to_str (int token);
-int lex_get_token (LEX *lf, int expect);
+LEX * lex_close_file (LEX *lf);
+LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
+int lex_get_char (LEX *lf);
+void lex_unget_char (LEX *lf);
+char * lex_tok_to_str (int token);
+int lex_get_token (LEX *lf, int expect);
/* message.c */
-void my_name_is (int argc, char *argv[], char *name);
-void init_msg (void *jcr, MSGS *msg);
-void term_msg (void);
-void close_msg (void *jcr);
-void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
-void Jmsg (void *jcr, int type, int level, char *fmt, ...);
-void dispatch_message (void *jcr, int type, int level, char *buf);
-void init_console_msg (char *wd);
-void free_msgs_res (MSGS *msgs);
-int open_spool_file (void *jcr, BSOCK *bs);
-int close_spool_file (void *vjcr, BSOCK *bs);
+void my_name_is (int argc, char *argv[], char *name);
+void init_msg (void *jcr, MSGS *msg);
+void term_msg (void);
+void close_msg (void *jcr);
+void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
+void Jmsg (void *jcr, int type, int level, char *fmt, ...);
+void dispatch_message (void *jcr, int type, int level, char *buf);
+void init_console_msg (char *wd);
+void free_msgs_res (MSGS *msgs);
+int open_spool_file (void *jcr, BSOCK *bs);
+int close_spool_file (void *vjcr, BSOCK *bs);
/* bnet_server.c */
-void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
- void *handle_client_request(void *bsock));
-void bnet_server (int port, void handle_client_request(BSOCK *bsock));
-int net_connect (int port);
-BSOCK * bnet_bind (int port);
-BSOCK * bnet_accept (BSOCK *bsock, char *who);
+void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
+ void *handle_client_request(void *bsock));
+void bnet_server (int port, void handle_client_request(BSOCK *bsock));
+int net_connect (int port);
+BSOCK * bnet_bind (int port);
+BSOCK * bnet_accept (BSOCK *bsock, char *who);
/* signal.c */
-void init_signals (void terminate(int sig));
-void init_stack_dump (void);
+void init_signals (void terminate(int sig));
+void init_stack_dump (void);
/* util.c */
-void lcase (char *str);
-void bash_spaces (char *str);
-void unbash_spaces (char *str);
-void strip_trailing_junk (char *str);
-void strip_trailing_slashes (char *dir);
-int skip_spaces (char **msg);
-int skip_nonspaces (char **msg);
-int fstrsch (char *a, char *b);
-char * encode_time (time_t time, char *buf);
-char * encode_mode (mode_t mode, char *buf);
-int do_shell_expansion (char *name);
-int is_buf_zero (char *buf, int len);
-void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
-void pm_strcat (POOLMEM **pm, char *str);
-void pm_strcpy (POOLMEM **pm, char *str);
-int run_program (char *prog, int wait, POOLMEM *results);
-char * job_type_to_str (int type);
-char * job_status_to_str (int stat);
-char * job_level_to_str (int level);
-void makeSessionKey (char *key, char *seed, int mode);
-BPIPE * open_bpipe(char *prog, int wait, char *mode);
-int close_wpipe(BPIPE *bpipe);
-int close_bpipe(BPIPE *bpipe);
-POOLMEM *edit_job_codes(void *jcr, char *omsg, char *imsg, char *to);
-void parse_command_args(POOLMEM *cmd, POOLMEM *args, int *argc,
- char **argk, char **argv);
-char *next_arg(char **s);
-
+void lcase (char *str);
+void bash_spaces (char *str);
+void unbash_spaces (char *str);
+void strip_trailing_junk (char *str);
+void strip_trailing_slashes (char *dir);
+int skip_spaces (char **msg);
+int skip_nonspaces (char **msg);
+int fstrsch (char *a, char *b);
+char * encode_time (time_t time, char *buf);
+char * encode_mode (mode_t mode, char *buf);
+int do_shell_expansion (char *name, int name_len);
+int is_buf_zero (char *buf, int len);
+void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
+void pm_strcat (POOLMEM **pm, char *str);
+void pm_strcpy (POOLMEM **pm, char *str);
+int run_program (char *prog, int wait, POOLMEM *results);
+char * job_type_to_str (int type);
+char * job_status_to_str (int stat);
+char * job_level_to_str (int level);
+void makeSessionKey (char *key, char *seed, int mode);
+BPIPE * open_bpipe(char *prog, int wait, char *mode);
+int close_wpipe(BPIPE *bpipe);
+int close_bpipe(BPIPE *bpipe);
+POOLMEM *edit_job_codes(void *jcr, char *omsg, char *imsg, char *to);
+void parse_command_args(POOLMEM *cmd, POOLMEM *args, int *argc,
+ char **argk, char **argv);
+char *next_arg(char **s);
+void set_working_directory(char *wd);
/* watchdog.c */
int start_watchdog(void);
}
-int do_shell_expansion(char *name)
+int do_shell_expansion(char *name, int name_len)
{
/* ****FIXME***** this should work for Win32 too */
#define UNIX
/* wait for child to exit */
while ((wpid = wait(&waitstatus)) != pid && wpid != -1)
{ ; }
- strcpy(name, echout);
+ strip_trailing_junk(echout);
+ if (strlen(echout) > 0) {
+ bstrncpy(name, echout, name_len);
+ }
stat = 1;
break;
}
}
#endif
}
+
+void set_working_directory(char *wd)
+{
+ struct stat stat_buf;
+
+ 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 */
+}
/* Check Configuration file for necessary info */
static void check_config()
{
- struct stat stat_buf;
-
LockRes();
me = (STORES *)GetNextRes(R_STORAGE, NULL);
if (!me) {
Emsg1(M_ERROR_TERM, 0, _("No Working Directory defined in %s. Cannot continue.\n"),
configfile);
}
- if (stat(me->working_directory, &stat_buf) != 0) {
- Emsg1(M_ERROR_TERM, 0, _("Working Directory: %s not found. Cannot continue.\n"),
- me->working_directory);
- }
- if (!S_ISDIR(stat_buf.st_mode)) {
- Emsg1(M_ERROR_TERM, 0, _("Working Directory: %s is not a directory. Cannot continue.\n"),
- me->working_directory);
- }
- working_directory = me->working_directory;
+
+ set_working_directory(me->working_directory);
}
/*
/* */
#define VERSION "1.31"
#define VSTRING "1"
-#define BDATE "20 May 2003"
-#define LSMDATE "20May03"
+#define BDATE "22 May 2003"
+#define LSMDATE "22May03"
/* Debug flags */
#define DEBUG 1