Example #1
0
// Copies the serial_slave_buffer to the master and sends the
// serial_master_buffer to the slave.
//
// Returns:
// 0 => no error
// 1 => slave did not respond
int serial_update_buffers(void) {
  // this code is very time dependent, so we need to disable interrupts
  cli();

  // signal to the slave that we want to start a transaction
  serial_output();
  serial_low();
  _delay_us(1);

  // wait for the slaves response
  serial_input();
  serial_high();
  _delay_us(SERIAL_DELAY);

  // check if the slave is present
  if (serial_read_pin()) {
    // slave failed to pull the line low, assume not present
    sei();
    return 1;
  }

  // if the slave is present syncronize with it
  sync_recv();

  uint8_t checksum_computed = 0;
  // receive data from the slave
  for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
    serial_slave_buffer[i] = serial_read_byte();
    sync_recv();
    checksum_computed += serial_slave_buffer[i];
  }
  uint8_t checksum_received = serial_read_byte();
  sync_recv();

  if (checksum_computed != checksum_received) {
    sei();
    return 1;
  }

  uint8_t checksum = 0;
  // send data to the slave
  for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
    serial_write_byte(serial_master_buffer[i]);
    sync_recv();
    checksum += serial_master_buffer[i];
  }
  serial_write_byte(checksum);
  sync_recv();

  // always, release the line when not in use
  serial_output();
  serial_high();

  sei();
  return 0;
}
Example #2
0
inline static
void change_reciver2sender(void) {
    sync_recv();     //0
    serial_delay();  //1
    serial_low();    //3
    serial_output(); //3
    serial_delay_half1(); //4
}
Example #3
0
static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
                                 int copy_attrs)
{
    copyinfo *filelist = 0;
    copyinfo *ci, *next;
    int pulled = 0;
    int skipped = 0;

    /* Make sure that both directory paths end in a slash. */
    if (rpath[0] == 0 || lpath[0] == 0) return -1;
    if (rpath[strlen(rpath) - 1] != '/') {
        int  tmplen = strlen(rpath) + 2;
        char *tmp = malloc(tmplen);
        if (tmp == 0) return -1;
        snprintf(tmp, tmplen, "%s/", rpath);
        rpath = tmp;
    }
    if (lpath[strlen(lpath) - 1] != '/') {
        int  tmplen = strlen(lpath) + 2;
        char *tmp = malloc(tmplen);
        if (tmp == 0) return -1;
        snprintf(tmp, tmplen, "%s/", lpath);
        lpath = tmp;
    }

    fprintf(stderr, "pull: building file list...\n");
    /* Recursively build the list of files to copy. */
    if (remote_build_list(fd, &filelist, rpath, lpath)) {
        return -1;
    }

    for (ci = filelist; ci != 0; ci = next) {
        next = ci->next;
        if (ci->flag == 0) {
            fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
            if (sync_recv(fd, ci->src, ci->dst, 0 /* no show progress */)) {
                return 1;
            }

            if (copy_attrs && set_time_and_mode(ci->dst, ci->time, ci->mode)) {
               return 1;
            }
            pulled++;
        } else {
            skipped++;
        }
        free(ci);
    }

    fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",
            pulled, (pulled == 1) ? "" : "s",
            skipped, (skipped == 1) ? "" : "s");

    return 0;
}
Example #4
0
static
uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) {
  uint8_t pecount = 0;
  for (uint8_t i = 0; i < size; ++i) {
    uint8_t data;
    sync_recv();
    data = serial_read_chunk(&pecount, 8);
    buffer[i] = data;
  }
  return pecount == 0;
}
int do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs) {
    std::string error;
    int fd = adb_connect("sync:", &error);
    if (fd < 0) {
        fprintf(stderr,"error: %s\n", error.c_str());
        return 1;
    }

    unsigned mode, time;
    if (sync_readtime(fd, rpath, &time, &mode)) {
        return 1;
    }
    if (mode == 0) {
        fprintf(stderr,"remote object '%s' does not exist\n", rpath);
        return 1;
    }

    if (S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
        std::string path_holder;
        struct stat st;
        if (stat(lpath, &st) == 0) {
            if (S_ISDIR(st.st_mode)) {
                // If we're copying a remote file to a local directory,
                // we really want to copy to local_dir + "/" + basename(remote).
                path_holder = android::base::StringPrintf("%s/%s", lpath, adb_basename(rpath).c_str());
                lpath = path_holder.c_str();
            }
        }
        BEGIN();
        if (sync_recv(fd, rpath, lpath, show_progress)) {
            return 1;
        } else {
            if (copy_attrs && set_time_and_mode(lpath, time, mode)) {
                return 1;
            }
        }
    } else if(S_ISDIR(mode)) {
        BEGIN();
        if (copy_remote_dir_local(fd, rpath, lpath, copy_attrs)) {
            return 1;
        }
    } else {
        fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);
        return 1;
    }
    END();
    sync_quit(fd);
    return 0;
}
int
main(int argc, char *argv[])
{
#ifdef __FreeBSD__
	extern char *__progname;
	FILE *fpid = NULL;
	struct stat dbstat;
	int pt, ge, we;  /* make build on amd64/sparc happy */
#endif
	fd_set *fdsr = NULL, *fdsw = NULL;
	struct sockaddr_in sin;
	struct sockaddr_in lin;
	int ch, s, s2, conflisten = 0, syncfd = 0, i, omax = 0, one = 1;
	socklen_t sinlen;
	u_short port;
	struct servent *ent;
	struct rlimit rlp;
	char *bind_address = NULL;
	const char *errstr;
	char *sync_iface = NULL;
	char *sync_baddr = NULL;

	tzset();
	openlog_r("spamd", LOG_PID | LOG_NDELAY, LOG_DAEMON, &sdata);

	if ((ent = getservbyname("spamd", "tcp")) == NULL)
		errx(1, "Can't find service \"spamd\" in /etc/services");
	port = ntohs(ent->s_port);
	if ((ent = getservbyname("spamd-cfg", "tcp")) == NULL)
		errx(1, "Can't find service \"spamd-cfg\" in /etc/services");
	cfg_port = ntohs(ent->s_port);
	if ((ent = getservbyname("spamd-sync", "udp")) == NULL)
		errx(1, "Can't find service \"spamd-sync\" in /etc/services");
	sync_port = ntohs(ent->s_port);

	if (gethostname(hostname, sizeof hostname) == -1)
		err(1, "gethostname");
	maxfiles = get_maxfiles();
	if (maxcon > maxfiles)
		maxcon = maxfiles;
	if (maxblack > maxfiles)
		maxblack = maxfiles;
	while ((ch =
#ifndef __FreeBSD__
	    getopt(argc, argv, "45l:c:B:p:bdG:h:s:S:M:n:vw:y:Y:")) != -1) {
#else
	    getopt(argc, argv, "45l:c:B:p:bdG:h:s:S:M:n:vw:y:Y:t:m:")) != -1) {
#endif
		switch (ch) {
		case '4':
			nreply = "450";
			break;
		case '5':
			nreply = "550";
			break;
		case 'l':
			bind_address = optarg;
			break;
		case 'B':
			i = atoi(optarg);
			maxblack = i;
			break;
		case 'c':
			i = atoi(optarg);
			if (i > maxfiles) {
				fprintf(stderr,
				    "%d > system max of %d connections\n",
				    i, maxfiles);
				usage();
			}
			maxcon = i;
			break;
		case 'p':
			i = atoi(optarg);
			port = i;
			break;
		case 'd':
			debug = 1;
			break;
		case 'b':
			greylist = 0;
			break;
		case 'G':
			if (sscanf(optarg, "%d:%d:%d", &pt, &ge, &we) != 3)
				usage();
			/* convert to seconds from minutes */
			passtime = pt * 60;
			/* convert to seconds from hours */
			whiteexp = we * (60 * 60);
			/* convert to seconds from hours */
			greyexp  = ge * (60 * 60);
			break;
		case 'h':
			bzero(&hostname, sizeof(hostname));
			if (strlcpy(hostname, optarg, sizeof(hostname)) >=
			    sizeof(hostname))
				errx(1, "-h arg too long");
			break;
		case 's':
			i = strtonum(optarg, 0, 10, &errstr);
			if (errstr)
				usage();
			stutter = i;
			break;
		case 'S':
			i = strtonum(optarg, 0, 90, &errstr);
			if (errstr)
				usage();
			grey_stutter = i;
			break;
		case 'M':
			low_prio_mx_ip = optarg;
			break;
		case 'n':
			spamd = optarg;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'w':
			window = atoi(optarg);
			if (window <= 0)
				usage();
			break;
		case 'Y':
			if (sync_addhost(optarg, sync_port) != 0)
				sync_iface = optarg;
			syncsend++;
			break;
		case 'y':
			sync_baddr = optarg;
			syncrecv++;
			break;
#ifdef __FreeBSD__
		case 't':
			ipfw_tabno = atoi(optarg);
			break;
		case 'm':
			if (strcmp(optarg, "ipfw") == 0)
				use_pf=0;
			break;
#endif
		default:
			usage();
			break;
		}
	}

#ifdef __FreeBSD__
	/* check if PATH_SPAMD_DB is a regular file */
	if (lstat(PATH_SPAMD_DB, &dbstat) == 0 && !S_ISREG(dbstat.st_mode)) {
		syslog(LOG_ERR, "error %s (Not a regular file)", PATH_SPAMD_DB);
		errx(1, "exit \"%s\" : Not a regular file", PATH_SPAMD_DB);
	}
#endif

	setproctitle("[priv]%s%s",
	    greylist ? " (greylist)" : "",
	    (syncrecv || syncsend) ? " (sync)" : "");

	if (!greylist)
		maxblack = maxcon;
	else if (maxblack > maxcon)
		usage();

	rlp.rlim_cur = rlp.rlim_max = maxcon + 15;
	if (setrlimit(RLIMIT_NOFILE, &rlp) == -1)
		err(1, "setrlimit");

	con = calloc(maxcon, sizeof(*con));
	if (con == NULL)
		err(1, "calloc");

	con->obuf = malloc(8192);

	if (con->obuf == NULL)
		err(1, "malloc");
	con->osize = 8192;

	for (i = 0; i < maxcon; i++)
		con[i].fd = -1;

	signal(SIGPIPE, SIG_IGN);

	s = socket(AF_INET, SOCK_STREAM, 0);
	if (s == -1)
		err(1, "socket");

	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one,
	    sizeof(one)) == -1)
		return (-1);

	conflisten = socket(AF_INET, SOCK_STREAM, 0);
	if (conflisten == -1)
		err(1, "socket");

	if (setsockopt(conflisten, SOL_SOCKET, SO_REUSEADDR, &one,
	    sizeof(one)) == -1)
		return (-1);

	memset(&sin, 0, sizeof sin);
	sin.sin_len = sizeof(sin);
	if (bind_address) {
		if (inet_pton(AF_INET, bind_address, &sin.sin_addr) != 1)
			err(1, "inet_pton");
	} else
		sin.sin_addr.s_addr = htonl(INADDR_ANY);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);

	if (bind(s, (struct sockaddr *)&sin, sizeof sin) == -1)
		err(1, "bind");

	memset(&lin, 0, sizeof sin);
	lin.sin_len = sizeof(sin);
	lin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	lin.sin_family = AF_INET;
	lin.sin_port = htons(cfg_port);

	if (bind(conflisten, (struct sockaddr *)&lin, sizeof lin) == -1)
		err(1, "bind local");

	if (syncsend || syncrecv) {
		syncfd = sync_init(sync_iface, sync_baddr, sync_port);
		if (syncfd == -1)
			err(1, "sync init");
	}

	if ((pw = getpwnam("_spamd")) == NULL)
		errx(1, "no such user _spamd");

#ifdef __FreeBSD__
	/* open the pid file just before daemon */
	fpid = fopen(pid_file, "w");
	if (fpid == NULL) {
		syslog(LOG_ERR, "error can't create pid file %s (%m)", pid_file);
		err(1, "can't create pid file \"%s\"", pid_file);
	}
#endif

	if (debug == 0) {
		if (daemon(1, 1) == -1)
			err(1, "daemon");
	}

	if (greylist) {
#ifdef __FreeBSD__
		if(use_pf){
#endif
			pfdev = open("/dev/pf", O_RDWR);
			if (pfdev == -1) {
				syslog_r(LOG_ERR, &sdata, "open /dev/pf: %m");
				exit(1);
			}
#ifdef __FreeBSD__
		}
#endif

		maxblack = (maxblack >= maxcon) ? maxcon - 100 : maxblack;
		if (maxblack < 0)
			maxblack = 0;

		/* open pipe to talk to greylister */
		if (pipe(greypipe) == -1) {
			syslog(LOG_ERR, "pipe (%m)");
			exit(1);
		}
		/* open pipe to recieve spamtrap configs */
		if (pipe(trappipe) == -1) {
			syslog(LOG_ERR, "pipe (%m)");
			exit(1);
		}
		jail_pid = fork();
		switch (jail_pid) {
		case -1:
			syslog(LOG_ERR, "fork (%m)");
			exit(1);
		case 0:
			/* child - continue */
			signal(SIGPIPE, SIG_IGN);
			grey = fdopen(greypipe[1], "w");
			if (grey == NULL) {
				syslog(LOG_ERR, "fdopen (%m)");
				_exit(1);
			}
			close(greypipe[0]);
			trapfd = trappipe[0];
			trapcfg = fdopen(trappipe[0], "r");
			if (trapcfg == NULL) {
				syslog(LOG_ERR, "fdopen (%m)");
				_exit(1);
			}
			close(trappipe[1]);
			goto jail;
		}
		/* parent - run greylister */
		grey = fdopen(greypipe[0], "r");
		if (grey == NULL) {
			syslog(LOG_ERR, "fdopen (%m)");
			exit(1);
		}
		close(greypipe[1]);
		trapcfg = fdopen(trappipe[1], "w");
		if (trapcfg == NULL) {
			syslog(LOG_ERR, "fdopen (%m)");
			exit(1);
		}
		close(trappipe[0]);
		return (greywatcher());
		/* NOTREACHED */
	}

jail:
#ifdef __FreeBSD__
	/* after switch user and daemon write and close the pid file */
	if (fpid) {
		fprintf(fpid, "%ld\n", (long) getpid());
		if (fclose(fpid) == EOF) {
			syslog(LOG_ERR, "error can't close pid file %s (%m)", pid_file);
			exit(1);
		}
	}
#endif

	if (chroot("/var/empty") == -1 || chdir("/") == -1) {
		syslog(LOG_ERR, "cannot chdir to /var/empty.");
		exit(1);
	}

	if (pw)
		if (setgroups(1, &pw->pw_gid) ||
		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
			err(1, "failed to drop privs");

	if (listen(s, 10) == -1)
		err(1, "listen");

	if (listen(conflisten, 10) == -1)
		err(1, "listen");

	if (debug != 0)
		printf("listening for incoming connections.\n");
	syslog_r(LOG_WARNING, &sdata, "listening for incoming connections.");

	while (1) {
		struct timeval tv, *tvp;
		int max, n;
		int writers;

		max = MAX(s, conflisten);
		if (syncrecv)
			max = MAX(max, syncfd);
		max = MAX(max, conffd);
		max = MAX(max, trapfd);

		time(&t);
		for (i = 0; i < maxcon; i++)
			if (con[i].fd != -1)
				max = MAX(max, con[i].fd);

		if (max > omax) {
			free(fdsr);
			fdsr = NULL;
			free(fdsw);
			fdsw = NULL;
			fdsr = (fd_set *)calloc(howmany(max+1, NFDBITS),
			    sizeof(fd_mask));
			if (fdsr == NULL)
				err(1, "calloc");
			fdsw = (fd_set *)calloc(howmany(max+1, NFDBITS),
			    sizeof(fd_mask));
			if (fdsw == NULL)
				err(1, "calloc");
			omax = max;
		} else {
			memset(fdsr, 0, howmany(max+1, NFDBITS) *
			    sizeof(fd_mask));
			memset(fdsw, 0, howmany(max+1, NFDBITS) *
			    sizeof(fd_mask));
		}

		writers = 0;
		for (i = 0; i < maxcon; i++) {
			if (con[i].fd != -1 && con[i].r) {
				if (con[i].r + MAXTIME <= t) {
					closecon(&con[i]);
					continue;
				}
				FD_SET(con[i].fd, fdsr);
			}
			if (con[i].fd != -1 && con[i].w) {
				if (con[i].w + MAXTIME <= t) {
					closecon(&con[i]);
					continue;
				}
				if (con[i].w <= t)
					FD_SET(con[i].fd, fdsw);
				writers = 1;
			}
		}
		FD_SET(s, fdsr);

		/* only one active config conn at a time */
		if (conffd == -1)
			FD_SET(conflisten, fdsr);
		else
			FD_SET(conffd, fdsr);
		if (trapfd != -1)
			FD_SET(trapfd, fdsr);
		if (syncrecv)
			FD_SET(syncfd, fdsr);

		if (writers == 0) {
			tvp = NULL;
		} else {
			tv.tv_sec = 1;
			tv.tv_usec = 0;
			tvp = &tv;
		}

		n = select(max+1, fdsr, fdsw, NULL, tvp);
		if (n == -1) {
			if (errno != EINTR)
				err(1, "select");
			continue;
		}
		if (n == 0)
			continue;

		for (i = 0; i < maxcon; i++) {
			if (con[i].fd != -1 && FD_ISSET(con[i].fd, fdsr))
				handler(&con[i]);
			if (con[i].fd != -1 && FD_ISSET(con[i].fd, fdsw))
				handlew(&con[i], clients + 5 < maxcon);
		}
		if (FD_ISSET(s, fdsr)) {
			sinlen = sizeof(sin);
			s2 = accept(s, (struct sockaddr *)&sin, &sinlen);
			if (s2 == -1)
				/* accept failed, they may try again */
				continue;
			for (i = 0; i < maxcon; i++)
				if (con[i].fd == -1)
					break;
			if (i == maxcon)
				close(s2);
			else {
				initcon(&con[i], s2, (struct sockaddr *)&sin);
				syslog_r(LOG_INFO, &sdata,
				    "%s: connected (%d/%d)%s%s",
				    con[i].addr, clients, blackcount,
				    ((con[i].lists == NULL) ? "" :
				    ", lists:"),
				    ((con[i].lists == NULL) ? "":
				    con[i].lists));
			}
		}
		if (FD_ISSET(conflisten, fdsr)) {
			sinlen = sizeof(lin);
			conffd = accept(conflisten, (struct sockaddr *)&lin,
			    &sinlen);
			if (conffd == -1)
				/* accept failed, they may try again */
				continue;
			else if (ntohs(lin.sin_port) >= IPPORT_RESERVED) {
				close(conffd);
				conffd = -1;
			}
		}
		if (conffd != -1 && FD_ISSET(conffd, fdsr))
			do_config();
		if (trapfd != -1 && FD_ISSET(trapfd, fdsr))
			read_configline(trapcfg);
		if (syncrecv && FD_ISSET(syncfd, fdsr))
			sync_recv();
	}
	exit(1);
}
Example #7
0
int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int copy_attrs)
{
    unsigned mode, time;
    struct stat st;

    int fd;

    fd = adb_connect("sync:");
    if(fd < 0) {
        fprintf(stderr,"error: %s\n", adb_error());
        return 1;
    }

    if(sync_readtime(fd, rpath, &time, &mode)) {
        return 1;
    }
    if(mode == 0) {
        fprintf(stderr,"remote object '%s' does not exist\n", rpath);
        return 1;
    }

    if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
        if(stat(lpath, &st) == 0) {
            if(S_ISDIR(st.st_mode)) {
                    /* if we're copying a remote file to a local directory,
                    ** we *really* want to copy to localdir + "/" + remotefilename
                    */
                const char *name = adb_dirstop(rpath);
                if(name == 0) {
                    name = rpath;
                } else {
                    name++;
                }
                int  tmplen = strlen(name) + strlen(lpath) + 2;
                char *tmp = malloc(tmplen);
                if(tmp == 0) return 1;
                snprintf(tmp, tmplen, "%s/%s", lpath, name);
                lpath = tmp;
            }
        }
        BEGIN();
        if (sync_recv(fd, rpath, lpath, show_progress)) {
            return 1;
        } else {
            if (copy_attrs && set_time_and_mode(lpath, time, mode))
                return 1;
            END();
            sync_quit(fd);
            return 0;
        }
    } else if(S_ISDIR(mode)) {
        BEGIN();
        if (copy_remote_dir_local(fd, rpath, lpath, copy_attrs)) {
            return 1;
        } else {
            END();
            sync_quit(fd);
            return 0;
        }
    } else {
        fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);
        return 1;
    }
}
static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
                                 int checktimestamps)
{
    copyinfo *filelist = 0;
    copyinfo *ci, *next;
    int pulled = 0;
    int skipped = 0;

    /* Make sure that both directory paths end in a slash. */
    if (rpath[0] == 0 || lpath[0] == 0) return -1;
    if (rpath[strlen(rpath) - 1] != '/') {
        int  tmplen = strlen(rpath) + 2;
        char *tmp = malloc(tmplen);
        if (tmp == 0) return -1;
        snprintf(tmp, tmplen, "%s/", rpath);
        rpath = tmp;
    }
    if (lpath[strlen(lpath) - 1] != '/') {
        int  tmplen = strlen(lpath) + 2;
        char *tmp = malloc(tmplen);
        if (tmp == 0) return -1;
        snprintf(tmp, tmplen, "%s/", lpath);
        lpath = tmp;
    }

    fprintf(stderr, "pull: building file list...\n");
    /* Recursively build the list of files to copy. */
    if (remote_build_list(fd, &filelist, rpath, lpath)) {
        return -1;
    }

#if 0
    if (checktimestamps) {
        for (ci = filelist; ci != 0; ci = ci->next) {
            if (sync_start_readtime(fd, ci->dst)) {
                return 1;
            }
        }
        for (ci = filelist; ci != 0; ci = ci->next) {
            unsigned int timestamp, mode, size;
            if (sync_finish_readtime(fd, &timestamp, &mode, &size))
                return 1;
            if (size == ci->size) {
                /* for links, we cannot update the atime/mtime */
                if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
                    (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
                    ci->flag = 1;
            }
        }
    }
#endif
    for (ci = filelist; ci != 0; ci = next) {
        next = ci->next;
        if (ci->flag == 0) {
            fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
            if (sync_recv(fd, ci->src, ci->dst)) {
                return 1;
            }
            pulled++;
        } else {
            skipped++;
        }
        free(ci);
    }

    fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",
            pulled, (pulled == 1) ? "" : "s",
            skipped, (skipped == 1) ? "" : "s");

    return 0;
}
static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
                                 int copy_attrs)
{
    copyinfo *filelist = 0;
    copyinfo *ci, *next;
    int pulled = 0;
    int skipped = 0;
    char *rpath_clean = NULL;
    char *lpath_clean = NULL;
    int ret = 0;

    if (rpath[0] == '\0' || lpath[0] == '\0') {
        ret = -1;
        goto finish;
    }

    /* Make sure that both directory paths end in a slash. */
    rpath_clean = add_slash_to_path(rpath);
    if (!rpath_clean) {
        ret = -1;
        goto finish;
    }
    lpath_clean = add_slash_to_path(lpath);
    if (!lpath_clean) {
        ret = -1;
        goto finish;
    }

    /* Recursively build the list of files to copy. */
    fprintf(stderr, "pull: building file list...\n");
    if (remote_build_list(fd, &filelist, rpath_clean, lpath_clean)) {
        ret = -1;
        goto finish;
    }

    for (ci = filelist; ci != 0; ci = next) {
        next = ci->next;
        if (ci->flag == 0) {
            fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
            if (sync_recv(fd, ci->src, ci->dst, 0 /* no show progress */)) {
                ret = -1;
                goto finish;
            }

            if (copy_attrs && set_time_and_mode(ci->dst, ci->time, ci->mode)) {
                ret = -1;
                goto finish;
            }
            pulled++;
        } else {
            skipped++;
        }
        free(ci);
    }

    fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",
            pulled, (pulled == 1) ? "" : "s",
            skipped, (skipped == 1) ? "" : "s");

finish:
    free(lpath_clean);
    free(rpath_clean);
    return ret;
}
Example #10
0
/*
 * Wait for packets to come in using poll().  When a packet comes in,
 * call receive_packet to receive the packet and possibly strip hardware
 * addressing information from it, and then call through the
 * bootp_packet_handler hook to try to do something with it.
 */
void
dispatch(void)
{
	int nfds, i, to_msec;
	struct protocol *l;
	static struct pollfd *fds;
	static int nfds_max;
	time_t howlong;

	for (nfds = 0, l = protocols; l; l = l->next)
		nfds++;
	if (syncfd != -1)
		nfds++;
	if (nfds > nfds_max) {
		fds = realloc(fds, nfds * sizeof(struct pollfd));
		if (fds == NULL)
			error("Can't allocate poll structures.");
		nfds_max = nfds;
	}

	for (;;) {
		/*
		 * Call any expired timeouts, and then if there's
		 * still a timeout registered, time out the poll
		 * call then.
		 */
		time(&cur_time);
another:
		if (timeouts) {
			if (timeouts->when <= cur_time) {
				struct dhcpd_timeout *t = timeouts;
				timeouts = timeouts->next;
				(*(t->func))(t->what);
				t->next = free_timeouts;
				free_timeouts = t;
				goto another;
			}

			/*
			 * Figure timeout in milliseconds, and check for
			 * potential overflow, so we can cram into an int
			 * for poll, while not polling with a negative
			 * timeout and blocking indefinitely.
			 */
			howlong = timeouts->when - cur_time;
			if (howlong > INT_MAX / 1000)
				howlong = INT_MAX / 1000;
			to_msec = howlong * 1000;
		} else
			to_msec = -1;

		/* Set up the descriptors to be polled. */
		for (i = 0, l = protocols; l; l = l->next) {
			struct interface_info *ip = l->local;

			if (ip && (l->handler != got_one || !ip->dead)) {
				fds[i].fd = l->fd;
				fds[i].events = POLLIN;
				++i;
			}
		}

		if (i == 0)
			error("No live interfaces to poll on - exiting.");

		if (syncfd != -1) {
			/* add syncer */
			fds[i].fd = syncfd;
			fds[i].events = POLLIN;
		}

		/* Wait for a packet or a timeout... */
		switch (poll(fds, nfds, to_msec)) {
		case -1:
			if (errno != EAGAIN && errno != EINTR)
				error("poll: %m");
			/* FALLTHROUGH */
		case 0:
			continue;	/* no packets */
		}
		time(&cur_time);

		for (i = 0, l = protocols; l; l = l->next) {
			struct interface_info *ip = l->local;

			if ((fds[i].revents & (POLLIN | POLLHUP))) {
				if (ip && (l->handler != got_one ||
				    !ip->dead))
					(*(l->handler))(l);
				if (interfaces_invalidated)
					break;
			}
			++i;
		}
		if ((syncfd != -1) && (fds[i].revents & (POLLIN | POLLHUP)))
			sync_recv();
		interfaces_invalidated = 0;
	}
}