Copyright (C) 1996-2000 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
- Copyright (C) 2001 by Martin Pool <mbp@samba.org>
+ Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
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
}
+static void print_child_argv(char **cmd)
+{
+ rprintf(FINFO, "opening connection using ");
+ for (; *cmd; cmd++) {
+ /* Look for characters that ought to be quoted. This
+ * is not a great quoting algorithm, but it's
+ * sufficient for a log message. */
+ if (strspn(*cmd, "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ ",.-_=+@/") != strlen(*cmd)) {
+ rprintf(FINFO, "\"%s\" ", *cmd);
+ } else {
+ rprintf(FINFO, "%s ", *cmd);
+ }
+ }
+ rprintf(FINFO, "\n");
+}
+
+
/* this is derived from CVS code
note that in the child STDIN is set to blocking and STDOUT
used to cope with badly broken rsh implementations like the one on
solaris.
*/
-pid_t piped_child(char **command,int *f_in,int *f_out)
+pid_t piped_child(char **command, int *f_in, int *f_out)
{
- pid_t pid;
- int to_child_pipe[2];
- int from_child_pipe[2];
- extern int blocking_io;
-
- if (fd_pair(to_child_pipe) < 0 ||
- fd_pair(from_child_pipe) < 0) {
- rprintf(FERROR,"pipe: %s\n",strerror(errno));
- exit_cleanup(RERR_IPC);
- }
-
-
- pid = do_fork();
- if (pid == -1) {
- rprintf(FERROR,"fork: %s\n",strerror(errno));
- exit_cleanup(RERR_IPC);
- }
-
- if (pid == 0)
- {
- extern int orig_umask;
- if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
- close(to_child_pipe[1]) < 0 ||
- close(from_child_pipe[0]) < 0 ||
- dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
- rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
- exit_cleanup(RERR_IPC);
- }
- if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
- if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
- umask(orig_umask);
- set_blocking(STDIN_FILENO);
- if (blocking_io) {
- set_blocking(STDOUT_FILENO);
- }
- execvp(command[0], command);
- rprintf(FERROR,"Failed to exec %s : %s\n",
- command[0],strerror(errno));
- exit_cleanup(RERR_IPC);
- }
+ pid_t pid;
+ int to_child_pipe[2];
+ int from_child_pipe[2];
+ extern int blocking_io;
+
+ if (verbose >= 2) {
+ print_child_argv(command);
+ }
+
+ if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
+ rprintf(FERROR, "pipe: %s\n", strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+
+
+ pid = do_fork();
+ if (pid == -1) {
+ rprintf(FERROR, "fork: %s\n", strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+
+ if (pid == 0) {
+ extern int orig_umask;
+ if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
+ close(to_child_pipe[1]) < 0 ||
+ close(from_child_pipe[0]) < 0 ||
+ dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
+ rprintf(FERROR, "Failed to dup/close : %s\n",
+ strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+ if (to_child_pipe[0] != STDIN_FILENO)
+ close(to_child_pipe[0]);
+ if (from_child_pipe[1] != STDOUT_FILENO)
+ close(from_child_pipe[1]);
+ umask(orig_umask);
+ set_blocking(STDIN_FILENO);
+ if (blocking_io) {
+ set_blocking(STDOUT_FILENO);
+ }
+ execvp(command[0], command);
+ rprintf(FERROR, "Failed to exec %s : %s\n",
+ command[0], strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
- if (close(from_child_pipe[1]) < 0 ||
- close(to_child_pipe[0]) < 0) {
- rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
- exit_cleanup(RERR_IPC);
- }
+ if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
+ rprintf(FERROR, "Failed to close : %s\n", strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
- *f_in = from_child_pipe[0];
- *f_out = to_child_pipe[1];
+ *f_in = from_child_pipe[0];
+ *f_out = to_child_pipe[1];
- return pid;
+ return pid;
}
pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
extern int am_sender;
extern int am_server;
- if (read_batch)
- am_sender = 0;
- else
- am_sender = !am_sender;
+ am_sender = read_batch ? 0 : !am_sender;
am_server = 1;
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
-int set_modtime(char *fname,time_t modtime)
+int set_modtime(char *fname, time_t modtime)
{
extern int dry_run;
- if (dry_run) return 0;
+ if (dry_run)
+ return 0;
+
+ if (verbose > 2) {
+ rprintf(FINFO, "set modtime of %s to (%ld) %s",
+ fname, (long) modtime,
+ asctime(localtime(&modtime)));
+ }
+
{
#ifdef HAVE_UTIMBUF
struct utimbuf tbuf;
derived from GNU C's cccp.c.
*/
-static int full_write(int desc, char *ptr, int len)
+static int full_write(int desc, char *ptr, size_t len)
{
int total_written;
for an error.
derived from GNU C's cccp.c. */
-static int safe_read(int desc, char *ptr, int len)
+static int safe_read(int desc, char *ptr, size_t len)
{
int n_chars;
- if (len <= 0)
+ if (len == 0)
return len;
#ifdef EINTR
static pid_t all_pids[10];
static int num_pids;
-/* fork and record the pid of the child */
+/** Fork and record the pid of the child. **/
pid_t do_fork(void)
{
pid_t newpid = fork();
- if (newpid) {
+ if (newpid != 0 && newpid != -1) {
all_pids[num_pids++] = newpid;
}
return newpid;
}
-/* kill all children */
+/**
+ * Kill all children.
+ *
+ * @todo It would be kind of nice to make sure that they are actually
+ * all our children before we kill them, because their pids may have
+ * been recycled by some other process. Perhaps when we wait for a
+ * child, we should remove it from this array. Alternatively we could
+ * perhaps use process groups, but I think that would not work on
+ * ancient Unix versions that don't support them.
+ **/
void kill_all(int sig)
{
int i;
- for (i=0;i<num_pids;i++) {
- if (all_pids[i] != getpid())
- kill(all_pids[i], sig);
+
+ for (i = 0; i < num_pids; i++) {
+ /* Let's just be a little careful where we
+ * point that gun, hey? See kill(2) for the
+ * magic caused by negative values. */
+ pid_t p = all_pids[i];
+
+ if (p == getpid())
+ continue;
+ if (p <= 0)
+ continue;
+
+ kill(p, sig);
}
}
+
/* turn a user name into a uid */
int name_to_uid(char *name, uid_t *uid)
{
globfree(&globbuf);
return;
}
- for (i=0; i<(maxargs - (*argc)) && i<globbuf.gl_pathc;i++) {
+ for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
if (i == 0) free(argv[*argc]);
argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
if (!argv[(*argc) + i]) out_of_memory("glob_expand");
{
int pct = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
unsigned long diff = msdiff(&start_time, now);
- double rate = diff ? ((ofs-start_ofs) / diff) * 1000.0/1024.0 : 0;
- const char *units, *rem_units;
- double remain = rate ? (size-ofs) / rate / 1000.0: 0.0;
+ double rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
+ const char *units;
+ /* If we've finished transferring this file, show the time taken;
+ * otherwise show expected time to complete. That's kind of
+ * inconsistent, but people can probably cope. Hopefully we'll
+ * get more consistent and complete progress reporting soon. --
+ * mbp */
+ double remain = is_last
+ ? (double) diff / 1000.0
+ : rate ? (double) (size-ofs) / rate / 1000.0 : 0.0;
int remain_h, remain_m, remain_s;
if (rate > 1024*1024) {