void sleeping(int sig) { char i; sig++; i = nox; nox = 1; statusbar(NULL); nox = i; if (idletime >= 0) idletime++; if (idletime == 2) (void) mono_change_online(who_am_i(NULL), "", 6); if (idletime == 5) /* if been idle for 5 minutes, put in wholist */ (void) mono_change_online(who_am_i(NULL), "", 2); #ifndef CLIENTSRC if ((idletime % TIMEOUT) == 0) { IFSYSOP { cprintf("\n\007\1f\1wBEEP! Idle Admin are bad for the BBS!\nLog out!\1a\n"); } else {
/** * If our C library can get malloc statistics, then show them to FINFO **/ static void show_malloc_stats(void) { #ifdef HAVE_MALLINFO struct mallinfo mi; mi = mallinfo(); rprintf(FINFO, "\n" RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n", getpid(), am_server ? "server " : "", am_daemon ? "daemon " : "", who_am_i()); rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n", (long)mi.arena); rprintf(FINFO, " ordblks: %10ld (chunks not in use)\n", (long)mi.ordblks); rprintf(FINFO, " smblks: %10ld\n", (long)mi.smblks); rprintf(FINFO, " hblks: %10ld (chunks from mmap)\n", (long)mi.hblks); rprintf(FINFO, " hblkhd: %10ld (bytes from mmap)\n", (long)mi.hblkhd); rprintf(FINFO, " allmem: %10ld (bytes from sbrk + mmap)\n", (long)mi.arena + mi.hblkhd); rprintf(FINFO, " usmblks: %10ld\n", (long)mi.usmblks); rprintf(FINFO, " fsmblks: %10ld\n", (long)mi.fsmblks); rprintf(FINFO, " uordblks: %10ld (bytes used)\n", (long)mi.uordblks); rprintf(FINFO, " fordblks: %10ld (bytes free)\n", (long)mi.fordblks); rprintf(FINFO, " keepcost: %10ld (bytes in releasable chunk)\n", (long)mi.keepcost); #endif /* HAVE_MALLINFO */ }
// Called when the user chooses to load a SIFT database. void FeaturesUI::cb_load_image_database_sift(Fl_Menu_ *o, void *v) { FeaturesDoc *doc = who_am_i(o)->doc; char *name = fl_file_chooser("Open File", "*.kdb", NULL); if (name != NULL) { doc->load_image_database(name, true); } }
// Called when the user chooses to load normal query features. void FeaturesUI::cb_load_query_features(Fl_Menu_ *o, void *v) { FeaturesDoc *doc = who_am_i(o)->doc; char *name = fl_file_chooser("Open File", "*.f", NULL); if (name != NULL) { doc->load_query_features(name, false); } }
// Called when the user chooses the "Load Query Image" menu item. void FeaturesUI::cb_load_query_image(Fl_Menu_ *o, void *v) { FeaturesDoc *doc = who_am_i(o)->doc; char *name = fl_file_chooser("Open File", "{*.p[gp]m,*.jpg}", NULL); if (name != NULL) { doc->load_query_image(name); } }
void kbicho (void *msg) { bicho_msg_s *m = msg; kbicho_s *b; b = ezalloc(sizeof(*b)); b->kb_key = m->q.q_passed_key; who_am_i(b); enq_dq( &Kbicho, b, kb_link); }
void gotocurr() { static int prev_rm = -1; quickroom = readquad(curr_rm); if (prev_rm != curr_rm) mono_change_online(who_am_i(NULL), quickroom.name, 5); prev_rm = curr_rm; return; }
/* * Called when the transfer is interrupted for some reason. * * Code is one of the RERR_* codes from errcode.h, or terminating * successfully. */ void log_exit(int code, const char *file, int line) { if (code == 0) { rprintf(FLOG,"sent %s bytes received %s bytes total size %s\n", big_num(stats.total_written), big_num(stats.total_read), big_num(stats.total_size)); } else if (am_server != 2) { const char *name; name = rerr_name(code); if (!name) name = "unexplained error"; /* VANISHED is not an error, only a warning */ if (code == RERR_VANISHED) { rprintf(FWARNING, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n", name, code, file, line, who_am_i(), RSYNC_VERSION); } else { rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n", name, code, file, line, who_am_i(), RSYNC_VERSION); } } }
/* This is only called by the sender. */ static void read_final_goodbye(int f_in, int f_out) { int i; if (protocol_version < 29) i = read_int(f_in); else { while ((i = read_int(f_in)) == the_file_list->count && read_shortint(f_in) == ITEM_IS_NEW) { /* Forward the keep-alive (no-op) to the receiver. */ write_int(f_out, the_file_list->count); write_shortint(f_out, ITEM_IS_NEW); } } if (i != -1) { rprintf(FERROR, "Invalid packet at end of run (%d) [%s]\n", i, who_am_i()); exit_cleanup(RERR_PROTOCOL); } }
/** * Make sure @p flist is big enough to hold at least @p flist->count * entries. **/ void flist_expand(struct file_list *flist) { struct file_struct **new_ptr; if (flist->count < flist->malloced) return; if (flist->malloced < FLIST_START) flist->malloced = FLIST_START; else if (flist->malloced >= FLIST_LINEAR) flist->malloced += FLIST_LINEAR; else flist->malloced *= 2; /* * In case count jumped or we are starting the list * with a known size just set it. */ if (flist->malloced < flist->count) flist->malloced = flist->count; new_ptr = realloc_array(flist->files, struct file_struct *, flist->malloced); if (verbose >= 2 && flist->malloced != FLIST_START) { rprintf(FINFO, "[%s] expand file_list to %.0f bytes, did%s move\n", who_am_i(), (double)sizeof flist->files[0] * flist->malloced, (new_ptr == flist->files) ? " not" : ""); } flist->files = new_ptr; if (!flist->files) out_of_memory("flist_expand"); }
int ntpdmain( int argc, char *argv[] ) { l_fp now; struct recvbuf *rbuf; const char * logfilename; # ifdef HAVE_UMASK mode_t uv; # endif # if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ uid_t uid; # endif # if defined(HAVE_WORKING_FORK) long wait_sync = 0; int pipe_fds[2]; int rc; int exit_code; # ifdef _AIX struct sigaction sa; # endif # if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY) int fid; # endif # endif /* HAVE_WORKING_FORK*/ # ifdef SCO5_CLOCK int fd; int zero; # endif # ifdef NEED_PTHREAD_WARMUP my_pthread_warmup(); # endif # ifdef HAVE_UMASK uv = umask(0); if (uv) umask(uv); else umask(022); # endif saved_argc = argc; saved_argv = argv; progname = argv[0]; initializing = TRUE; /* mark that we are initializing */ parse_cmdline_opts(&argc, &argv); # ifdef DEBUG debug = OPT_VALUE_SET_DEBUG_LEVEL; # ifdef HAVE_SETLINEBUF setlinebuf(stdout); # endif # endif if (HAVE_OPT(NOFORK) || HAVE_OPT(QUIT) # ifdef DEBUG || debug # endif || HAVE_OPT(SAVECONFIGQUIT)) nofork = TRUE; init_logging(progname, NLOG_SYNCMASK, TRUE); /* honor -l/--logfile option to log to a file */ if (HAVE_OPT(LOGFILE)) { logfilename = OPT_ARG(LOGFILE); syslogit = FALSE; change_logfile(logfilename, FALSE); } else { logfilename = NULL; if (nofork) msyslog_term = TRUE; if (HAVE_OPT(SAVECONFIGQUIT)) syslogit = FALSE; } msyslog(LOG_NOTICE, "%s: Starting", Version); { int i; char buf[1024]; /* Secret knowledge of msyslog buf length */ char *cp = buf; /* Note that every arg has an initial space character */ snprintf(cp, sizeof(buf), "Command line:"); cp += strlen(cp); for (i = 0; i < saved_argc ; ++i) { snprintf(cp, sizeof(buf) - (cp - buf), " %s", saved_argv[i]); cp += strlen(cp); } msyslog(LOG_INFO, "%s", buf); } /* * Install trap handlers to log errors and assertion failures. * Default handlers print to stderr which doesn't work if detached. */ isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); /* MPE lacks the concept of root */ # if defined(HAVE_GETUID) && !defined(MPE) uid = getuid(); if (uid && !HAVE_OPT( SAVECONFIGQUIT )) { msyslog_term = TRUE; msyslog(LOG_ERR, "must be run as root, not uid %ld", (long)uid); exit(1); } # endif /* * Enable the Multi-Media Timer for Windows? */ # ifdef SYS_WINNT if (HAVE_OPT( MODIFYMMTIMER )) set_mm_timer(MM_TIMER_HIRES); # endif #ifdef HAVE_DNSREGISTRATION /* * Enable mDNS registrations? */ if (HAVE_OPT( MDNS )) { mdnsreg = TRUE; } #endif /* HAVE_DNSREGISTRATION */ if (HAVE_OPT( NOVIRTUALIPS )) listen_to_virtual_ips = 0; /* * --interface, listen on specified interfaces */ if (HAVE_OPT( INTERFACE )) { int ifacect = STACKCT_OPT( INTERFACE ); const char** ifaces = STACKLST_OPT( INTERFACE ); sockaddr_u addr; while (ifacect-- > 0) { add_nic_rule( is_ip_address(*ifaces, AF_UNSPEC, &addr) ? MATCH_IFADDR : MATCH_IFNAME, *ifaces, -1, ACTION_LISTEN); ifaces++; } } if (HAVE_OPT( NICE )) priority_done = 0; # ifdef HAVE_SCHED_SETSCHEDULER if (HAVE_OPT( PRIORITY )) { config_priority = OPT_VALUE_PRIORITY; config_priority_override = 1; priority_done = 0; } # endif # ifdef HAVE_WORKING_FORK /* make sure the FDs are initialised */ pipe_fds[0] = -1; pipe_fds[1] = -1; do { /* 'loop' once */ if (!HAVE_OPT( WAIT_SYNC )) break; wait_sync = OPT_VALUE_WAIT_SYNC; if (wait_sync <= 0) { wait_sync = 0; break; } /* -w requires a fork() even with debug > 0 */ nofork = FALSE; if (pipe(pipe_fds)) { exit_code = (errno) ? errno : -1; msyslog(LOG_ERR, "Pipe creation failed for --wait-sync: %m"); exit(exit_code); } waitsync_fd_to_close = pipe_fds[1]; } while (0); /* 'loop' once */ # endif /* HAVE_WORKING_FORK */ init_lib(); # ifdef SYS_WINNT /* * Start interpolation thread, must occur before first * get_systime() */ init_winnt_time(); # endif /* * Initialize random generator and public key pair */ get_systime(&now); ntp_srandom((int)(now.l_i * now.l_uf)); /* * Detach us from the terminal. May need an #ifndef GIZMO. */ if (!nofork) { # ifdef HAVE_WORKING_FORK rc = fork(); if (-1 == rc) { exit_code = (errno) ? errno : -1; msyslog(LOG_ERR, "fork: %m"); exit(exit_code); } if (rc > 0) { /* parent */ exit_code = wait_child_sync_if(pipe_fds[0], wait_sync); exit(exit_code); } /* * child/daemon * close all open files excepting waitsync_fd_to_close. * msyslog() unreliable until after init_logging(). */ closelog(); if (syslog_file != NULL) { fclose(syslog_file); syslog_file = NULL; syslogit = TRUE; } close_all_except(waitsync_fd_to_close); INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \ && 2 == dup2(0, 2)); init_logging(progname, 0, TRUE); /* we lost our logfile (if any) daemonizing */ setup_logfile(logfilename); # ifdef SYS_DOMAINOS { uid_$t puid; status_$t st; proc2_$who_am_i(&puid); proc2_$make_server(&puid, &st); } # endif /* SYS_DOMAINOS */ # ifdef HAVE_SETSID if (setsid() == (pid_t)-1) msyslog(LOG_ERR, "setsid(): %m"); # elif defined(HAVE_SETPGID) if (setpgid(0, 0) == -1) msyslog(LOG_ERR, "setpgid(): %m"); # else /* !HAVE_SETSID && !HAVE_SETPGID follows */ # ifdef TIOCNOTTY fid = open("/dev/tty", 2); if (fid >= 0) { ioctl(fid, (u_long)TIOCNOTTY, NULL); close(fid); } # endif /* TIOCNOTTY */ ntp_setpgrp(0, getpid()); # endif /* !HAVE_SETSID && !HAVE_SETPGID */ # ifdef _AIX /* Don't get killed by low-on-memory signal. */ sa.sa_handler = catch_danger; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGDANGER, &sa, NULL); # endif /* _AIX */ # endif /* HAVE_WORKING_FORK */ } # ifdef SCO5_CLOCK /* * SCO OpenServer's system clock offers much more precise timekeeping * on the base CPU than the other CPUs (for multiprocessor systems), * so we must lock to the base CPU. */ fd = open("/dev/at1", O_RDONLY); if (fd >= 0) { zero = 0; if (ioctl(fd, ACPU_LOCK, &zero) < 0) msyslog(LOG_ERR, "cannot lock to base CPU: %m"); close(fd); } # endif /* Setup stack size in preparation for locking pages in memory. */ # if defined(HAVE_MLOCKALL) # ifdef HAVE_SETRLIMIT ntp_rlimit(RLIMIT_STACK, DFLT_RLIMIT_STACK * 4096, 4096, "4k"); # ifdef RLIMIT_MEMLOCK /* * The default RLIMIT_MEMLOCK is very low on Linux systems. * Unless we increase this limit malloc calls are likely to * fail if we drop root privilege. To be useful the value * has to be larger than the largest ntpd resident set size. */ ntp_rlimit(RLIMIT_MEMLOCK, DFLT_RLIMIT_MEMLOCK * 1024 * 1024, 1024 * 1024, "MB"); # endif /* RLIMIT_MEMLOCK */ # endif /* HAVE_SETRLIMIT */ # else /* !HAVE_MLOCKALL follows */ # ifdef HAVE_PLOCK # ifdef PROCLOCK # ifdef _AIX /* * set the stack limit for AIX for plock(). * see get_aix_stack() for more info. */ if (ulimit(SET_STACKLIM, (get_aix_stack() - 8 * 4096)) < 0) msyslog(LOG_ERR, "Cannot adjust stack limit for plock: %m"); # endif /* _AIX */ # endif /* PROCLOCK */ # endif /* HAVE_PLOCK */ # endif /* !HAVE_MLOCKALL */ /* * Set up signals we pay attention to locally. */ # ifdef SIGDIE1 signal_no_reset(SIGDIE1, finish); signal_no_reset(SIGDIE2, finish); signal_no_reset(SIGDIE3, finish); signal_no_reset(SIGDIE4, finish); # endif # ifdef SIGBUS signal_no_reset(SIGBUS, finish); # endif # if !defined(SYS_WINNT) && !defined(VMS) # ifdef DEBUG (void) signal_no_reset(MOREDEBUGSIG, moredebug); (void) signal_no_reset(LESSDEBUGSIG, lessdebug); # else (void) signal_no_reset(MOREDEBUGSIG, no_debug); (void) signal_no_reset(LESSDEBUGSIG, no_debug); # endif /* DEBUG */ # endif /* !SYS_WINNT && !VMS */ /* * Set up signals we should never pay attention to. */ # ifdef SIGPIPE signal_no_reset(SIGPIPE, SIG_IGN); # endif /* * Call the init_ routines to initialize the data structures. * * Exactly what command-line options are we expecting here? */ INIT_SSL(); init_auth(); init_util(); init_restrict(); init_mon(); init_timer(); init_request(); init_control(); init_peer(); # ifdef REFCLOCK init_refclock(); # endif set_process_priority(); init_proto(); /* Call at high priority */ init_io(); init_loopfilter(); mon_start(MON_ON); /* monitor on by default now */ /* turn off in config if unwanted */ /* * Get the configuration. This is done in a separate module * since this will definitely be different for the gizmo board. */ getconfig(argc, argv); if (-1 == cur_memlock) { # if defined(HAVE_MLOCKALL) /* * lock the process into memory */ if ( !HAVE_OPT(SAVECONFIGQUIT) # ifdef RLIMIT_MEMLOCK && -1 != DFLT_RLIMIT_MEMLOCK # endif && 0 != mlockall(MCL_CURRENT|MCL_FUTURE)) msyslog(LOG_ERR, "mlockall(): %m"); # else /* !HAVE_MLOCKALL follows */ # ifdef HAVE_PLOCK # ifdef PROCLOCK /* * lock the process into memory */ if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(PROCLOCK)) msyslog(LOG_ERR, "plock(PROCLOCK): %m"); # else /* !PROCLOCK follows */ # ifdef TXTLOCK /* * Lock text into ram */ if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(TXTLOCK)) msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); # else /* !TXTLOCK follows */ msyslog(LOG_ERR, "plock() - don't know what to lock!"); # endif /* !TXTLOCK */ # endif /* !PROCLOCK */ # endif /* HAVE_PLOCK */ # endif /* !HAVE_MLOCKALL */ } loop_config(LOOP_DRIFTINIT, 0); report_event(EVNT_SYSRESTART, NULL, NULL); initializing = FALSE; # ifdef HAVE_DROPROOT if (droproot) { /* Drop super-user privileges and chroot now if the OS supports this */ # ifdef HAVE_LINUX_CAPABILITIES /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */ if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) { msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" ); exit(-1); } # elif HAVE_SOLARIS_PRIVS /* Nothing to do here */ # else /* we need a user to switch to */ if (user == NULL) { msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" ); exit(-1); } # endif /* HAVE_LINUX_CAPABILITIES || HAVE_SOLARIS_PRIVS */ if (user != NULL) { if (isdigit((unsigned char)*user)) { sw_uid = (uid_t)strtoul(user, &endp, 0); if (*endp != '\0') goto getuser; if ((pw = getpwuid(sw_uid)) != NULL) { free(user); user = estrdup(pw->pw_name); sw_gid = pw->pw_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find user ID %s", user); exit (-1); } } else { getuser: errno = 0; if ((pw = getpwnam(user)) != NULL) { sw_uid = pw->pw_uid; sw_gid = pw->pw_gid; } else { if (errno) msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user); else msyslog(LOG_ERR, "Cannot find user `%s'", user); exit (-1); } } } if (group != NULL) { if (isdigit((unsigned char)*group)) { sw_gid = (gid_t)strtoul(group, &endp, 0); if (*endp != '\0') goto getgroup; } else { getgroup: if ((gr = getgrnam(group)) != NULL) { sw_gid = gr->gr_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find group `%s'", group); exit (-1); } } } if (chrootdir ) { /* make sure cwd is inside the jail: */ if (chdir(chrootdir)) { msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir); exit (-1); } if (chroot(chrootdir)) { msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir); exit (-1); } if (chdir("/")) { msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m"); exit (-1); } } # ifdef HAVE_SOLARIS_PRIVS if ((lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) { msyslog(LOG_ERR, "priv_str_to_set() failed:%m"); exit(-1); } if ((highprivs = priv_allocset()) == NULL) { msyslog(LOG_ERR, "priv_allocset() failed:%m"); exit(-1); } (void) getppriv(PRIV_PERMITTED, highprivs); (void) priv_intersect(highprivs, lowprivs); if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) { msyslog(LOG_ERR, "setppriv() failed:%m"); exit(-1); } # endif /* HAVE_SOLARIS_PRIVS */ if (user && initgroups(user, sw_gid)) { msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user); exit (-1); } if (group && setgid(sw_gid)) { msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group); exit (-1); } if (group && setegid(sw_gid)) { msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group); exit (-1); } if (group) { if (0 != setgroups(1, &sw_gid)) { msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid); exit (-1); } } else if (pw) if (0 != initgroups(pw->pw_name, pw->pw_gid)) { msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid); exit (-1); } if (user && setuid(sw_uid)) { msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user); exit (-1); } if (user && seteuid(sw_uid)) { msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user); exit (-1); } # if !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS) /* * for now assume that the privilege to bind to privileged ports * is associated with running with uid 0 - should be refined on * ports that allow binding to NTP_PORT with uid != 0 */ disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */ # endif /* !HAVE_LINUX_CAPABILITIES && !HAVE_SOLARIS_PRIVS */ if (disable_dynamic_updates && interface_interval) { interface_interval = 0; msyslog(LOG_INFO, "running as non-root disables dynamic interface tracking"); } # ifdef HAVE_LINUX_CAPABILITIES { /* * We may be running under non-root uid now, but we still hold full root privileges! * We drop all of them, except for the crucial one or two: cap_sys_time and * cap_net_bind_service if doing dynamic interface tracking. */ cap_t caps; char *captext; captext = (0 != interface_interval) ? "cap_sys_time,cap_net_bind_service=pe" : "cap_sys_time=pe"; caps = cap_from_text(captext); if (!caps) { msyslog(LOG_ERR, "cap_from_text(%s) failed: %m", captext); exit(-1); } if (-1 == cap_set_proc(caps)) { msyslog(LOG_ERR, "cap_set_proc() failed to drop root privs: %m"); exit(-1); } cap_free(caps); } # endif /* HAVE_LINUX_CAPABILITIES */ # ifdef HAVE_SOLARIS_PRIVS if (priv_delset(lowprivs, "proc_setid") == -1) { msyslog(LOG_ERR, "priv_delset() failed:%m"); exit(-1); } if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) { msyslog(LOG_ERR, "setppriv() failed:%m"); exit(-1); } priv_freeset(lowprivs); priv_freeset(highprivs); # endif /* HAVE_SOLARIS_PRIVS */ root_dropped = TRUE; fork_deferred_worker(); } /* if (droproot) */ # endif /* HAVE_DROPROOT */ /* libssecomp sandboxing */ #if defined (LIBSECCOMP) && (KERN_SECCOMP) scmp_filter_ctx ctx; if ((ctx = seccomp_init(SCMP_ACT_KILL)) < 0) msyslog(LOG_ERR, "%s: seccomp_init(SCMP_ACT_KILL) failed: %m", __func__); else { msyslog(LOG_DEBUG, "%s: seccomp_init(SCMP_ACT_KILL) succeeded", __func__); } #ifdef __x86_64__ int scmp_sc[] = { SCMP_SYS(adjtimex), SCMP_SYS(bind), SCMP_SYS(brk), SCMP_SYS(chdir), SCMP_SYS(clock_gettime), SCMP_SYS(clock_settime), SCMP_SYS(close), SCMP_SYS(connect), SCMP_SYS(exit_group), SCMP_SYS(fstat), SCMP_SYS(fsync), SCMP_SYS(futex), SCMP_SYS(getitimer), SCMP_SYS(getsockname), SCMP_SYS(ioctl), SCMP_SYS(lseek), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(munmap), SCMP_SYS(open), SCMP_SYS(poll), SCMP_SYS(read), SCMP_SYS(recvmsg), SCMP_SYS(rename), SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigprocmask), SCMP_SYS(rt_sigreturn), SCMP_SYS(select), SCMP_SYS(sendto), SCMP_SYS(setitimer), SCMP_SYS(setsid), SCMP_SYS(socket), SCMP_SYS(stat), SCMP_SYS(time), SCMP_SYS(write), }; #endif #ifdef __i386__ int scmp_sc[] = { SCMP_SYS(_newselect), SCMP_SYS(adjtimex), SCMP_SYS(brk), SCMP_SYS(chdir), SCMP_SYS(clock_gettime), SCMP_SYS(clock_settime), SCMP_SYS(close), SCMP_SYS(exit_group), SCMP_SYS(fsync), SCMP_SYS(futex), SCMP_SYS(getitimer), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(mmap2), SCMP_SYS(munmap), SCMP_SYS(open), SCMP_SYS(poll), SCMP_SYS(read), SCMP_SYS(rename), SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigprocmask), SCMP_SYS(select), SCMP_SYS(setitimer), SCMP_SYS(setsid), SCMP_SYS(sigprocmask), SCMP_SYS(sigreturn), SCMP_SYS(socketcall), SCMP_SYS(stat64), SCMP_SYS(time), SCMP_SYS(write), }; #endif { int i; for (i = 0; i < COUNTOF(scmp_sc); i++) { if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, scmp_sc[i], 0) < 0) { msyslog(LOG_ERR, "%s: seccomp_rule_add() failed: %m", __func__); } } } if (seccomp_load(ctx) < 0) msyslog(LOG_ERR, "%s: seccomp_load() failed: %m", __func__); else { msyslog(LOG_DEBUG, "%s: seccomp_load() succeeded", __func__); } #endif /* LIBSECCOMP and KERN_SECCOMP */ # ifdef HAVE_IO_COMPLETION_PORT for (;;) { GetReceivedBuffers(); # else /* normal I/O */ BLOCK_IO_AND_ALARM(); was_alarmed = FALSE; for (;;) { if (alarm_flag) { /* alarmed? */ was_alarmed = TRUE; alarm_flag = FALSE; } if (!was_alarmed && !has_full_recv_buffer()) { /* * Nothing to do. Wait for something. */ io_handler(); } if (alarm_flag) { /* alarmed? */ was_alarmed = TRUE; alarm_flag = FALSE; } if (was_alarmed) { UNBLOCK_IO_AND_ALARM(); /* * Out here, signals are unblocked. Call timer routine * to process expiry. */ timer(); was_alarmed = FALSE; BLOCK_IO_AND_ALARM(); } # endif /* !HAVE_IO_COMPLETION_PORT */ # ifdef DEBUG_TIMING { l_fp pts; l_fp tsa, tsb; int bufcount = 0; get_systime(&pts); tsa = pts; # endif rbuf = get_full_recv_buffer(); while (rbuf != NULL) { if (alarm_flag) { was_alarmed = TRUE; alarm_flag = FALSE; } UNBLOCK_IO_AND_ALARM(); if (was_alarmed) { /* avoid timer starvation during lengthy I/O handling */ timer(); was_alarmed = FALSE; } /* * Call the data procedure to handle each received * packet. */ if (rbuf->receiver != NULL) { # ifdef DEBUG_TIMING l_fp dts = pts; L_SUB(&dts, &rbuf->recv_time); DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9))); collect_timing(rbuf, "buffer processing delay", 1, &dts); bufcount++; # endif (*rbuf->receiver)(rbuf); } else { msyslog(LOG_ERR, "fatal: receive buffer callback NULL"); abort(); } BLOCK_IO_AND_ALARM(); freerecvbuf(rbuf); rbuf = get_full_recv_buffer(); } # ifdef DEBUG_TIMING get_systime(&tsb); L_SUB(&tsb, &tsa); if (bufcount) { collect_timing(NULL, "processing", bufcount, &tsb); DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9))); } } # endif /* * Go around again */ # ifdef HAVE_DNSREGISTRATION if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) { mdnsreg = current_time; msyslog(LOG_INFO, "Attempting to register mDNS"); if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) { if (!--mdnstries) { msyslog(LOG_ERR, "Unable to register mDNS, giving up."); } else { msyslog(LOG_INFO, "Unable to register mDNS, will try later."); } } else { msyslog(LOG_INFO, "mDNS service registered."); mdnsreg = FALSE; } } # endif /* HAVE_DNSREGISTRATION */ } UNBLOCK_IO_AND_ALARM(); return 1; } #endif /* !SIM */ #if !defined(SIM) && defined(SIGDIE1) /* * finish - exit gracefully */ static RETSIGTYPE finish( int sig ) { const char *sig_desc; sig_desc = NULL; #ifdef HAVE_STRSIGNAL sig_desc = strsignal(sig); #endif if (sig_desc == NULL) sig_desc = ""; msyslog(LOG_NOTICE, "%s exiting on signal %d (%s)", progname, sig, sig_desc); /* See Bug 2513 and Bug 2522 re the unlink of PIDFILE */ # ifdef HAVE_DNSREGISTRATION if (mdns != NULL) DNSServiceRefDeallocate(mdns); # endif peer_cleanup(); exit(0); } #endif /* !SIM && SIGDIE1 */ #ifndef SIM /* * wait_child_sync_if - implements parent side of -w/--wait-sync */ # ifdef HAVE_WORKING_FORK static int wait_child_sync_if( int pipe_read_fd, long wait_sync ) { int rc; int exit_code; time_t wait_end_time; time_t cur_time; time_t wait_rem; fd_set readset; struct timeval wtimeout; if (0 == wait_sync) return 0; /* waitsync_fd_to_close used solely by child */ close(waitsync_fd_to_close); wait_end_time = time(NULL) + wait_sync; do { cur_time = time(NULL); wait_rem = (wait_end_time > cur_time) ? (wait_end_time - cur_time) : 0; wtimeout.tv_sec = wait_rem; wtimeout.tv_usec = 0; FD_ZERO(&readset); FD_SET(pipe_read_fd, &readset); rc = select(pipe_read_fd + 1, &readset, NULL, NULL, &wtimeout); if (-1 == rc) { if (EINTR == errno) continue; exit_code = (errno) ? errno : -1; msyslog(LOG_ERR, "--wait-sync select failed: %m"); return exit_code; } if (0 == rc) { /* * select() indicated a timeout, but in case * its timeouts are affected by a step of the * system clock, select() again with a zero * timeout to confirm. */ FD_ZERO(&readset); FD_SET(pipe_read_fd, &readset); wtimeout.tv_sec = 0; wtimeout.tv_usec = 0; rc = select(pipe_read_fd + 1, &readset, NULL, NULL, &wtimeout); if (0 == rc) /* select() timeout */ break; else /* readable */ return 0; } else /* readable */ return 0; } while (wait_rem > 0); fprintf(stderr, "%s: -w/--wait-sync %ld timed out.\n", progname, wait_sync); return ETIMEDOUT; }
void ProcessEvent(unsigned int me, time_type now, int event_type, event_content_type *event_content, unsigned int size, void *pointer) { state_type *state = (state_type *) pointer; char *conf_file = NULL, *conf_file_1 = NULL, *conf_file_2 = NULL; simulation_conf configuration; int i; // Upon reception of INIT, install the simulation state if (event_type == INIT) { // Get the file to load the configuration from for (i = 0; i < size; i += 2) { if (checkParameter("conf-file", event_content, i)) { conf_file = getParameter(event_content, i+1); } else if(checkParameter("conf-file_1", event_content, i)) { conf_file_1 = getParameter(event_content, i+1); } else if(checkParameter("conf-file_2", event_content, i)) { conf_file_2 = getParameter(event_content, i+1); } } // Sanity check if (conf_file == NULL) { fprintf(stderr, "Configuration file not specified. Please set conf-file before running the simulation.\n"); exit(-1); } // Try to load the configuration if (!configuration_parse(&configuration, conf_file)) { fprintf(stderr, "Error loading configuration file %s\n", conf_file); exit(-1); } if(configuration.client_conf.data_items_access_distribution==TOPKEYS){ if(!configuration_parse_top_keys(&configuration,"PUTS",conf_file_1)){ fprintf(stderr, "Error loading puts topkeys' configuration file"); exit(-1); } if(!configuration_parse_top_keys(&configuration,"GETS",conf_file_2)){ fprintf(stderr, "Error loading gets topkeys' configuration file"); exit(-1); } /*int x; for(x=0; x<configuration.cache_objects;x++){ if(configuration.client_conf.topkeys_cache_objects_get_probability[x]==0) break; printf("%f\n",configuration.client_conf.topkeys_cache_objects_get_probability[x]); }*/ } // Allocate simulation state state = (state_type *) malloc(sizeof(state_type)); SetState(state); // Store the global configuration state->start_stat_time = configuration.start_stat_time; state->num_clients = configuration.num_clients; state->num_servers = configuration.num_servers; state->cache_objects = configuration.cache_objects; state->object_replication_degree = configuration.object_replication_degree; state->average_server_to_server_net_delay = configuration.average_server_to_server_net_delay; state->average_client_to_server_net_delay = configuration.average_client_to_server_net_delay; // Now, depending on who I am, store the remainder of the configuration switch (who_am_i(me, state)) { case CLIENT: state->type.client_state.configuration = configuration.client_conf; break; case SERVER: state->type.server_state.configuration = configuration.server_conf; break; default: fprintf(stderr, "Internal error at %s:%d\n", __FILE__, __LINE__); break; } } // Dispatch the event to the correct handler switch (who_am_i(me, state)) { case CLIENT: CLIENT_ProcessEvent(me, now, event_type, event_content, size, state); break; case SERVER: SERVER_ProcessEvent(me, now, event_type, event_content, size, state); break; default: fprintf(stderr, "Internal error at %s:%d\n", __FILE__, __LINE__); break; } }
/* * Main program. Initialize us, disconnect us from the tty if necessary, * and loop waiting for I/O and/or timer expiries. */ int ntpdmain( int argc, char *argv[] ) { l_fp now; struct recvbuf *rbuf; #ifdef _AIX /* HMS: ifdef SIGDANGER? */ struct sigaction sa; #endif progname = argv[0]; initializing = 1; /* mark that we are initializing */ process_commandline_opts(&argc, &argv); init_logging(progname, 1); /* Open the log file */ char *error = NULL; if (sandbox_init("ntpd", SANDBOX_NAMED, &error) == -1) { msyslog(LOG_ERR, "sandbox_init(ntpd, SANDBOX_NAMED) failed: %s", error); sandbox_free_error(error); } #ifdef HAVE_UMASK { mode_t uv; uv = umask(0); if(uv) (void) umask(uv); else (void) umask(022); } #endif #if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ { uid_t uid; uid = getuid(); if (uid && !HAVE_OPT( SAVECONFIGQUIT )) { msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid); printf("must be run as root, not uid %ld\n", (long)uid); exit(1); } } #endif /* getstartup(argc, argv); / * startup configuration, may set debug */ #ifdef DEBUG debug = DESC(DEBUG_LEVEL).optOccCt; DPRINTF(1, ("%s\n", Version)); #endif /* honor -l/--logfile option to log to a file */ setup_logfile(); /* * Enable the Multi-Media Timer for Windows? */ #ifdef SYS_WINNT if (HAVE_OPT( MODIFYMMTIMER )) set_mm_timer(MM_TIMER_HIRES); #endif if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT ) #ifdef DEBUG || debug #endif || HAVE_OPT( SAVECONFIGQUIT )) nofork = 1; if (HAVE_OPT( NOVIRTUALIPS )) listen_to_virtual_ips = 0; /* * --interface, listen on specified interfaces */ if (HAVE_OPT( INTERFACE )) { int ifacect = STACKCT_OPT( INTERFACE ); const char** ifaces = STACKLST_OPT( INTERFACE ); isc_netaddr_t netaddr; while (ifacect-- > 0) { add_nic_rule( is_ip_address(*ifaces, &netaddr) ? MATCH_IFADDR : MATCH_IFNAME, *ifaces, -1, ACTION_LISTEN); ifaces++; } } if (HAVE_OPT( NICE )) priority_done = 0; #if defined(HAVE_SCHED_SETSCHEDULER) if (HAVE_OPT( PRIORITY )) { config_priority = OPT_VALUE_PRIORITY; config_priority_override = 1; priority_done = 0; } #endif #ifdef SYS_WINNT /* * Start interpolation thread, must occur before first * get_systime() */ init_winnt_time(); #endif /* * Initialize random generator and public key pair */ get_systime(&now); ntp_srandom((int)(now.l_i * now.l_uf)); #if !defined(VMS) # ifndef NODETACH /* * Detach us from the terminal. May need an #ifndef GIZMO. */ if (!nofork) { /* * Install trap handlers to log errors and assertion * failures. Default handlers print to stderr which * doesn't work if detached. */ isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); # ifndef SYS_WINNT # ifdef HAVE_DAEMON daemon(0, 0); # else /* not HAVE_DAEMON */ if (fork()) /* HMS: What about a -1? */ exit(0); { #if !defined(F_CLOSEM) u_long s; int max_fd; #endif /* !FCLOSEM */ if (syslog_file != NULL) { fclose(syslog_file); syslog_file = NULL; } #if defined(F_CLOSEM) /* * From 'Writing Reliable AIX Daemons,' SG24-4946-00, * by Eric Agar (saves us from doing 32767 system * calls) */ if (fcntl(0, F_CLOSEM, 0) == -1) msyslog(LOG_ERR, "ntpd: failed to close open files(): %m"); #else /* not F_CLOSEM */ # if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) max_fd = sysconf(_SC_OPEN_MAX); # else /* HAVE_SYSCONF && _SC_OPEN_MAX */ max_fd = getdtablesize(); # endif /* HAVE_SYSCONF && _SC_OPEN_MAX */ for (s = 0; s < max_fd; s++) (void) close((int)s); #endif /* not F_CLOSEM */ (void) open("/", 0); (void) dup2(0, 1); (void) dup2(0, 2); init_logging(progname, 0); /* we lost our logfile (if any) daemonizing */ setup_logfile(); #ifdef SYS_DOMAINOS { uid_$t puid; status_$t st; proc2_$who_am_i(&puid); proc2_$make_server(&puid, &st); } #endif /* SYS_DOMAINOS */ #if defined(HAVE_SETPGID) || defined(HAVE_SETSID) # ifdef HAVE_SETSID if (setsid() == (pid_t)-1) msyslog(LOG_ERR, "ntpd: setsid(): %m"); # else if (setpgid(0, 0) == -1) msyslog(LOG_ERR, "ntpd: setpgid(): %m"); # endif #else /* HAVE_SETPGID || HAVE_SETSID */ { # if defined(TIOCNOTTY) int fid; fid = open("/dev/tty", 2); if (fid >= 0) { (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0); (void) close(fid); } # endif /* defined(TIOCNOTTY) */ # ifdef HAVE_SETPGRP_0 (void) setpgrp(); # else /* HAVE_SETPGRP_0 */ (void) setpgrp(0, getpid()); # endif /* HAVE_SETPGRP_0 */ } #endif /* HAVE_SETPGID || HAVE_SETSID */ #ifdef _AIX /* Don't get killed by low-on-memory signal. */ sa.sa_handler = catch_danger; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; (void) sigaction(SIGDANGER, &sa, NULL); #endif /* _AIX */ } # endif /* not HAVE_DAEMON */ # endif /* SYS_WINNT */ } # endif /* NODETACH */ #endif /* VMS */ #ifdef SCO5_CLOCK /* * SCO OpenServer's system clock offers much more precise timekeeping * on the base CPU than the other CPUs (for multiprocessor systems), * so we must lock to the base CPU. */ { int fd = open("/dev/at1", O_RDONLY); if (fd >= 0) { int zero = 0; if (ioctl(fd, ACPU_LOCK, &zero) < 0) msyslog(LOG_ERR, "cannot lock to base CPU: %m"); close( fd ); } /* else ... * If we can't open the device, this probably just isn't * a multiprocessor system, so we're A-OK. */ } #endif #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE) # ifdef HAVE_SETRLIMIT /* * Set the stack limit to something smaller, so that we don't lock a lot * of unused stack memory. */ { struct rlimit rl; /* HMS: must make the rlim_cur amount configurable */ if (getrlimit(RLIMIT_STACK, &rl) != -1 && (rl.rlim_cur = 50 * 4096) < rl.rlim_max) { if (setrlimit(RLIMIT_STACK, &rl) == -1) { msyslog(LOG_ERR, "Cannot adjust stack limit for mlockall: %m"); } } # ifdef RLIMIT_MEMLOCK /* * The default RLIMIT_MEMLOCK is very low on Linux systems. * Unless we increase this limit malloc calls are likely to * fail if we drop root privlege. To be useful the value * has to be larger than the largest ntpd resident set size. */ rl.rlim_cur = rl.rlim_max = 32*1024*1024; if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) { msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); } # endif /* RLIMIT_MEMLOCK */ } # endif /* HAVE_SETRLIMIT */ /* * lock the process into memory */ if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) msyslog(LOG_ERR, "mlockall(): %m"); #else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ # ifdef HAVE_PLOCK # ifdef PROCLOCK # ifdef _AIX /* * set the stack limit for AIX for plock(). * see get_aix_stack() for more info. */ if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0) { msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m"); } # endif /* _AIX */ /* * lock the process into memory */ if (plock(PROCLOCK) < 0) msyslog(LOG_ERR, "plock(PROCLOCK): %m"); # else /* not PROCLOCK */ # ifdef TXTLOCK /* * Lock text into ram */ if (plock(TXTLOCK) < 0) msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); # else /* not TXTLOCK */ msyslog(LOG_ERR, "plock() - don't know what to lock!"); # endif /* not TXTLOCK */ # endif /* not PROCLOCK */ # endif /* HAVE_PLOCK */ #endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ /* * Set up signals we pay attention to locally. */ #ifdef SIGDIE1 (void) signal_no_reset(SIGDIE1, finish); #endif /* SIGDIE1 */ #ifdef SIGDIE2 (void) signal_no_reset(SIGDIE2, finish); #endif /* SIGDIE2 */ #ifdef SIGDIE3 (void) signal_no_reset(SIGDIE3, finish); #endif /* SIGDIE3 */ #ifdef SIGDIE4 (void) signal_no_reset(SIGDIE4, finish); #endif /* SIGDIE4 */ #ifdef SIGBUS (void) signal_no_reset(SIGBUS, finish); #endif /* SIGBUS */ #if !defined(SYS_WINNT) && !defined(VMS) # ifdef DEBUG (void) signal_no_reset(MOREDEBUGSIG, moredebug); (void) signal_no_reset(LESSDEBUGSIG, lessdebug); # else (void) signal_no_reset(MOREDEBUGSIG, no_debug); (void) signal_no_reset(LESSDEBUGSIG, no_debug); # endif /* DEBUG */ #endif /* !SYS_WINNT && !VMS */ /* * Set up signals we should never pay attention to. */ #if defined SIGPIPE (void) signal_no_reset(SIGPIPE, SIG_IGN); #endif /* SIGPIPE */ /* * Call the init_ routines to initialize the data structures. * * Exactly what command-line options are we expecting here? */ init_auth(); init_util(); init_restrict(); init_mon(); init_timer(); init_lib(); init_request(); init_control(); init_peer(); #ifdef REFCLOCK init_refclock(); #endif set_process_priority(); init_proto(); /* Call at high priority */ init_io(); init_loopfilter(); mon_start(MON_ON); /* monitor on by default now */ /* turn off in config if unwanted */ /* * Get the configuration. This is done in a separate module * since this will definitely be different for the gizmo board. */ getconfig(argc, argv); NLOG(NLOG_SYSINFO) /* 'if' clause for syslog */ msyslog(LOG_NOTICE, "%s", Version); report_event(EVNT_SYSRESTART, NULL, NULL); loop_config(LOOP_DRIFTCOMP, old_drift); initializing = 0; #ifdef HAVE_DROPROOT if( droproot ) { /* Drop super-user privileges and chroot now if the OS supports this */ #ifdef HAVE_LINUX_CAPABILITIES /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */ if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) { msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" ); exit(-1); } #else /* we need a user to switch to */ if (user == NULL) { msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" ); exit(-1); } #endif /* HAVE_LINUX_CAPABILITIES */ if (user != NULL) { if (isdigit((unsigned char)*user)) { sw_uid = (uid_t)strtoul(user, &endp, 0); if (*endp != '\0') goto getuser; if ((pw = getpwuid(sw_uid)) != NULL) { user = strdup(pw->pw_name); if (NULL == user) { msyslog(LOG_ERR, "strdup() failed: %m"); exit (-1); } sw_gid = pw->pw_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find user ID %s", user); exit (-1); } } else { getuser: errno = 0; if ((pw = getpwnam(user)) != NULL) { sw_uid = pw->pw_uid; sw_gid = pw->pw_gid; } else { if (errno) msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user); else msyslog(LOG_ERR, "Cannot find user `%s'", user); exit (-1); } } } if (group != NULL) { if (isdigit((unsigned char)*group)) { sw_gid = (gid_t)strtoul(group, &endp, 0); if (*endp != '\0') goto getgroup; } else { getgroup: if ((gr = getgrnam(group)) != NULL) { sw_gid = gr->gr_gid; } else { errno = 0; msyslog(LOG_ERR, "Cannot find group `%s'", group); exit (-1); } } } if (chrootdir ) { /* make sure cwd is inside the jail: */ if (chdir(chrootdir)) { msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir); exit (-1); } if (chroot(chrootdir)) { msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir); exit (-1); } if (chdir("/")) { msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m"); exit (-1); } } if (user && initgroups(user, sw_gid)) { msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user); exit (-1); } if (group && setgid(sw_gid)) { msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group); exit (-1); } if (group && setegid(sw_gid)) { msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group); exit (-1); } if (user && setuid(sw_uid)) { msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user); exit (-1); } if (user && seteuid(sw_uid)) { msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user); exit (-1); } #ifndef HAVE_LINUX_CAPABILITIES /* * for now assume that the privilege to bind to privileged ports * is associated with running with uid 0 - should be refined on * ports that allow binding to NTP_PORT with uid != 0 */ disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */ #endif if (disable_dynamic_updates && interface_interval) { interface_interval = 0; msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking"); } #ifdef HAVE_LINUX_CAPABILITIES do { /* * We may be running under non-root uid now, but we still hold full root privileges! * We drop all of them, except for the crucial one or two: cap_sys_time and * cap_net_bind_service if doing dynamic interface tracking. */ cap_t caps; char *captext = (interface_interval) ? "cap_sys_time,cap_net_bind_service=ipe" : "cap_sys_time=ipe"; if( ! ( caps = cap_from_text( captext ) ) ) { msyslog( LOG_ERR, "cap_from_text() failed: %m" ); exit(-1); } if( cap_set_proc( caps ) == -1 ) { msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" ); exit(-1); } cap_free( caps ); } while(0); #endif /* HAVE_LINUX_CAPABILITIES */ } /* if( droproot ) */ #endif /* HAVE_DROPROOT */ /* * Use select() on all on all input fd's for unlimited * time. select() will terminate on SIGALARM or on the * reception of input. Using select() means we can't do * robust signal handling and we get a potential race * between checking for alarms and doing the select(). * Mostly harmless, I think. */ /* On VMS, I suspect that select() can't be interrupted * by a "signal" either, so I take the easy way out and * have select() time out after one second. * System clock updates really aren't time-critical, * and - lacking a hardware reference clock - I have * yet to learn about anything else that is. */ #if defined(HAVE_IO_COMPLETION_PORT) for (;;) { GetReceivedBuffers(); #else /* normal I/O */ BLOCK_IO_AND_ALARM(); was_alarmed = 0; for (;;) { # if !defined(HAVE_SIGNALED_IO) extern fd_set activefds; extern int maxactivefd; fd_set rdfdes; int nfound; # endif if (alarm_flag) /* alarmed? */ { was_alarmed = 1; alarm_flag = 0; } if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE) { /* * Nothing to do. Wait for something. */ # ifndef HAVE_SIGNALED_IO rdfdes = activefds; # if defined(VMS) || defined(SYS_VXWORKS) /* make select() wake up after one second */ { struct timeval t1; t1.tv_sec = 1; t1.tv_usec = 0; nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, (fd_set *)0, &t1); } # else nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, (fd_set *)0, (struct timeval *)0); # endif /* VMS */ if (nfound > 0) { l_fp ts; get_systime(&ts); (void)input_handler(&ts); } else if (nfound == -1 && errno != EINTR) msyslog(LOG_ERR, "select() error: %m"); # ifdef DEBUG else if (debug > 5) msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); # endif /* DEBUG */ # else /* HAVE_SIGNALED_IO */ wait_for_signal(); # endif /* HAVE_SIGNALED_IO */ if (alarm_flag) /* alarmed? */ { was_alarmed = 1; alarm_flag = 0; } } if (was_alarmed) { UNBLOCK_IO_AND_ALARM(); /* * Out here, signals are unblocked. Call timer routine * to process expiry. */ timer(); was_alarmed = 0; BLOCK_IO_AND_ALARM(); } #endif /* ! HAVE_IO_COMPLETION_PORT */ #ifdef DEBUG_TIMING { l_fp pts; l_fp tsa, tsb; int bufcount = 0; get_systime(&pts); tsa = pts; #endif rbuf = get_full_recv_buffer(); while (rbuf != NULL) { if (alarm_flag) { was_alarmed = 1; alarm_flag = 0; } UNBLOCK_IO_AND_ALARM(); if (was_alarmed) { /* avoid timer starvation during lengthy I/O handling */ timer(); was_alarmed = 0; } /* * Call the data procedure to handle each received * packet. */ if (rbuf->receiver != NULL) /* This should always be true */ { #ifdef DEBUG_TIMING l_fp dts = pts; L_SUB(&dts, &rbuf->recv_time); DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9))); collect_timing(rbuf, "buffer processing delay", 1, &dts); bufcount++; #endif (rbuf->receiver)(rbuf); } else { msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING"); abort(); } BLOCK_IO_AND_ALARM(); freerecvbuf(rbuf); rbuf = get_full_recv_buffer(); } #ifdef DEBUG_TIMING get_systime(&tsb); L_SUB(&tsb, &tsa); if (bufcount) { collect_timing(NULL, "processing", bufcount, &tsb); DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9))); } } #endif /* * Go around again */ #ifdef HAVE_DNSREGISTRATION if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) { mdnsreg = current_time; msyslog(LOG_INFO, "Attemping to register mDNS"); if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) { if (!--mdnstries) { msyslog(LOG_ERR, "Unable to register mDNS, giving up."); } else { msyslog(LOG_INFO, "Unable to register mDNS, will try later."); } } else { msyslog(LOG_INFO, "mDNS service registered."); mdnsreg = 0; } } #endif /* HAVE_DNSREGISTRATION */ } UNBLOCK_IO_AND_ALARM(); return 1; } #ifdef SIGDIE2 /* * finish - exit gracefully */ static RETSIGTYPE finish( int sig ) { msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig); #ifdef HAVE_DNSREGISTRATION if (mdns != NULL) DNSServiceRefDeallocate(mdns); #endif switch (sig) { # ifdef SIGBUS case SIGBUS: printf("\nfinish(SIGBUS)\n"); exit(0); # endif case 0: /* Should never happen... */ return; default: exit(0); } }
// Called when the user chooses the "Toggle Features" menu item. void FeaturesUI::cb_toggle_features(Fl_Menu_ *o, void *v) { who_am_i(o)->queryView->toggleFeatures(); who_am_i(o)->resultView->toggleFeatures(); who_am_i(o)->refresh(); }
/* this is the underlying (unformatted) rsync debugging function. Call * it with FINFO, FERROR_*, FWARNING, FLOG, or FCLIENT. Note: recursion * can happen with certain fatal conditions. */ void rwrite(enum logcode code, const char *buf, int len, int is_utf8) { int trailing_CR_or_NL; FILE *f = msgs2stderr ? stderr : stdout; #ifdef ICONV_OPTION iconv_t ic = is_utf8 && ic_recv != (iconv_t)-1 ? ic_recv : ic_chck; #else #ifdef ICONV_CONST iconv_t ic = ic_chck; #endif #endif if (len < 0) exit_cleanup(RERR_MESSAGEIO); if (msgs2stderr) { if (!am_daemon) { if (code == FLOG) return; goto output_msg; } if (code == FCLIENT) return; code = FLOG; } else if (send_msgs_to_gen) { assert(!is_utf8); /* Pass the message to our sibling in native charset. */ send_msg((enum msgcode)code, buf, len, 0); return; } if (code == FERROR_SOCKET) /* This gets simplified for a non-sibling. */ code = FERROR; else if (code == FERROR_UTF8) { is_utf8 = 1; code = FERROR; } if (code == FCLIENT) code = FINFO; else if (am_daemon || logfile_name) { static int in_block; char msg[2048]; int priority = code == FINFO || code == FLOG ? LOG_INFO : LOG_WARNING; if (in_block) return; in_block = 1; if (!log_initialised) log_init(0); strlcpy(msg, buf, MIN((int)sizeof msg, len + 1)); logit(priority, msg); in_block = 0; if (code == FLOG || (am_daemon && !am_server)) return; } else if (code == FLOG) return; if (quiet && code == FINFO) return; if (am_server) { enum msgcode msg = (enum msgcode)code; if (protocol_version < 30) { if (msg == MSG_ERROR) msg = MSG_ERROR_XFER; else if (msg == MSG_WARNING) msg = MSG_INFO; } /* Pass the message to the non-server side. */ if (send_msg(msg, buf, len, !is_utf8)) return; if (am_daemon) { /* TODO: can we send the error to the user somehow? */ return; } f = stderr; } output_msg: switch (code) { case FERROR_XFER: got_xfer_error = 1; /* FALL THROUGH */ case FERROR: case FERROR_UTF8: case FERROR_SOCKET: case FWARNING: f = stderr; break; case FLOG: case FINFO: case FCLIENT: break; default: fprintf(stderr, "Unknown logcode in rwrite(): %d [%s]\n", (int)code, who_am_i()); exit_cleanup(RERR_MESSAGEIO); } if (output_needs_newline) { fputc('\n', f); output_needs_newline = 0; } trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r') ? buf[--len] : 0; if (len && buf[0] == '\r') { fputc('\r', f); buf++; len--; } #ifdef ICONV_CONST if (ic != (iconv_t)-1) { xbuf outbuf, inbuf; char convbuf[1024]; int ierrno; INIT_CONST_XBUF(outbuf, convbuf); INIT_XBUF(inbuf, (char*)buf, len, (size_t)-1); while (inbuf.len) { iconvbufs(ic, &inbuf, &outbuf, inbuf.pos ? 0 : ICB_INIT); ierrno = errno; if (outbuf.len) { filtered_fwrite(f, convbuf, outbuf.len, 0); outbuf.len = 0; } if (!ierrno || ierrno == E2BIG) continue; fprintf(f, "\\#%03o", CVAL(inbuf.buf, inbuf.pos++)); inbuf.len--; } } else #endif filtered_fwrite(f, buf, len, !allow_8bit_chars); if (trailing_CR_or_NL) { fputc(trailing_CR_or_NL, f); fflush(f); } }
NORETURN void out_of_memory(const char *str) { rprintf(FERROR, "ERROR: out of memory in %s [%s]\n", str, who_am_i()); exit_cleanup(RERR_MALLOC); }
int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, char *buf, int *len_ptr) { int len, iflags = 0; struct file_list *flist; uchar fnamecmp_type = FNAMECMP_FNAME; int ndx, save_verbose = verbose; read_loop: while (1) { ndx = read_ndx(f_in); if (ndx >= 0) break; if (ndx == NDX_DONE) return ndx; if (!inc_recurse || am_sender) { int last; if (first_flist) last = first_flist->prev->ndx_start + first_flist->prev->used - 1; else last = -1; rprintf(FERROR, "Invalid file index: %d (%d - %d) [%s]\n", ndx, NDX_DONE, last, who_am_i()); exit_cleanup(RERR_PROTOCOL); } if (ndx == NDX_FLIST_EOF) { flist_eof = 1; send_msg(MSG_FLIST_EOF, "", 0, 0); continue; } ndx = NDX_FLIST_OFFSET - ndx; if (ndx < 0 || ndx >= dir_flist->used) { ndx = NDX_FLIST_OFFSET - ndx; rprintf(FERROR, "Invalid dir index: %d (%d - %d) [%s]\n", ndx, NDX_FLIST_OFFSET, NDX_FLIST_OFFSET - dir_flist->used + 1, who_am_i()); exit_cleanup(RERR_PROTOCOL); } /* Send everything read from f_in to msg_fd_out. */ if (verbose > 3) { rprintf(FINFO, "[%s] receiving flist for dir %d\n", who_am_i(), ndx); } verbose = 0; send_msg_int(MSG_FLIST, ndx); start_flist_forward(f_in); flist = recv_file_list(f_in); flist->parent_ndx = ndx; stop_flist_forward(); verbose = save_verbose; } iflags = protocol_version >= 29 ? read_shortint(f_in) : ITEM_TRANSFER | ITEM_MISSING_DATA; /* Support the protocol-29 keep-alive style. */ if (protocol_version < 30 && ndx == cur_flist->used && iflags == ITEM_IS_NEW) { if (am_sender) maybe_send_keepalive(); goto read_loop; } cur_flist = flist_for_ndx(ndx, "read_ndx_and_attrs"); if (iflags & ITEM_BASIS_TYPE_FOLLOWS) fnamecmp_type = read_byte(f_in); *type_ptr = fnamecmp_type; if (iflags & ITEM_XNAME_FOLLOWS) { if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0) exit_cleanup(RERR_PROTOCOL); } else { *buf = '\0'; len = -1; } *len_ptr = len; if (iflags & ITEM_TRANSFER) { int i = ndx - cur_flist->ndx_start; struct file_struct *file = cur_flist->files[i]; if (i < 0 || !(S_ISREG(file->mode) || (copy_devices && IS_DEVICE(file->mode)))) { rprintf(FERROR, "received request to transfer non-regular file: %d [%s]\n", ndx, who_am_i()); exit_cleanup(RERR_PROTOCOL); } } *iflag_ptr = iflags; return ndx; }
/** * main routine for receiver process. * * Receiver process runs on the same host as the generator process. */ int recv_files(int f_in, struct file_list *flist, char *local_name) { int next_gen_i = -1; int fd1,fd2; STRUCT_STAT st; int iflags, xlen; char *fname, fbuf[MAXPATHLEN]; char xname[MAXPATHLEN]; char fnametmp[MAXPATHLEN]; char *fnamecmp, *partialptr, numbuf[4]; char fnamecmpbuf[MAXPATHLEN]; uchar fnamecmp_type; struct file_struct *file; struct stats initial_stats; int save_make_backups = make_backups; int itemizing = am_daemon ? daemon_log_format_has_i : !am_server && log_format_has_i; int max_phase = protocol_version >= 29 ? 2 : 1; int i, recv_ok; if (verbose > 2) rprintf(FINFO,"recv_files(%d) starting\n",flist->count); if (flist->hlink_pool) { pool_destroy(flist->hlink_pool); flist->hlink_pool = NULL; } if (delay_updates) init_delayed_bits(flist->count); while (1) { cleanup_disable(); i = read_int(f_in); if (i == -1) { if (read_batch) { get_next_gen_i(batch_gen_fd, next_gen_i, flist->count); next_gen_i = -1; } if (++phase > max_phase) break; csum_length = SUM_LENGTH; if (verbose > 2) rprintf(FINFO, "recv_files phase=%d\n", phase); if (phase == 2 && delay_updates) handle_delayed_updates(flist, local_name); send_msg(MSG_DONE, "", 0); if (keep_partial && !partial_dir) make_backups = 0; /* prevents double backup */ continue; } iflags = read_item_attrs(f_in, -1, i, &fnamecmp_type, xname, &xlen); if (iflags == ITEM_IS_NEW) /* no-op packet */ continue; file = flist->files[i]; fname = local_name ? local_name : f_name_to(file, fbuf); if (verbose > 2) rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname)); if (!(iflags & ITEM_TRANSFER)) { maybe_log_item(file, iflags, itemizing, xname); continue; } if (phase == 2) { rprintf(FERROR, "got transfer request in phase 2 [%s]\n", who_am_i()); exit_cleanup(RERR_PROTOCOL); } stats.current_file_index = i; stats.num_transferred_files++; stats.total_transferred_size += file->length; cleanup_got_literal = 0; if (server_filter_list.head && check_filter(&server_filter_list, fname, 0) < 0) { rprintf(FERROR, "attempt to hack rsync failed.\n"); exit_cleanup(RERR_PROTOCOL); } if (!do_xfers) { /* log the transfer */ if (!am_server && log_format) log_item(file, &stats, iflags, NULL); if (read_batch) discard_receive_data(f_in, file->length); continue; } if (write_batch < 0) { log_item(file, &stats, iflags, NULL); if (!am_server) discard_receive_data(f_in, file->length); continue; } if (read_batch) { next_gen_i = get_next_gen_i(batch_gen_fd, next_gen_i, i); if (i < next_gen_i) { rprintf(FINFO, "(Skipping batched update for \"%s\")\n", safe_fname(fname)); discard_receive_data(f_in, file->length); continue; } next_gen_i = -1; } partialptr = partial_dir ? partial_dir_fname(fname) : fname; if (protocol_version >= 29) { switch (fnamecmp_type) { case FNAMECMP_FNAME: fnamecmp = fname; break; case FNAMECMP_PARTIAL_DIR: fnamecmp = partialptr; break; case FNAMECMP_BACKUP: fnamecmp = get_backup_name(fname); break; case FNAMECMP_FUZZY: if (file->dirname) { pathjoin(fnamecmpbuf, MAXPATHLEN, file->dirname, xname); fnamecmp = fnamecmpbuf; } else fnamecmp = xname; break; default: if (fnamecmp_type >= basis_dir_cnt) { rprintf(FERROR, "invalid basis_dir index: %d.\n", fnamecmp_type); exit_cleanup(RERR_PROTOCOL); } pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], fname); fnamecmp = fnamecmpbuf; break; } if (!fnamecmp || (server_filter_list.head && check_filter(&server_filter_list, fname, 0) < 0)) fnamecmp = fname; } else { /* Reminder: --inplace && --partial-dir are never * enabled at the same time. */ if (inplace && make_backups) { if (!(fnamecmp = get_backup_name(fname))) fnamecmp = fname; } else if (partial_dir && partialptr) fnamecmp = partialptr; else fnamecmp = fname; } initial_stats = stats; /* open the file */ fd1 = do_open(fnamecmp, O_RDONLY, 0); if (fd1 == -1 && protocol_version < 29) { if (fnamecmp != fname) { fnamecmp = fname; fd1 = do_open(fnamecmp, O_RDONLY, 0); } if (fd1 == -1 && basis_dir[0]) { /* pre-29 allowed only one alternate basis */ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[0], fname); fnamecmp = fnamecmpbuf; fd1 = do_open(fnamecmp, O_RDONLY, 0); } } if (fd1 != -1 && do_fstat(fd1,&st) != 0) { rsyserr(FERROR, errno, "fstat %s failed", full_fname(fnamecmp)); discard_receive_data(f_in, file->length); close(fd1); continue; } if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) { /* this special handling for directories * wouldn't be necessary if robust_rename() * and the underlying robust_unlink could cope * with directories */ rprintf(FERROR,"recv_files: %s is a directory\n", full_fname(fnamecmp)); discard_receive_data(f_in, file->length); close(fd1); continue; } if (fd1 != -1 && !S_ISREG(st.st_mode)) { close(fd1); fd1 = -1; } if (fd1 != -1 && !preserve_perms) { /* if the file exists already and we aren't preserving * permissions then act as though the remote end sent * us the file permissions we already have */ file->mode = st.st_mode; } /* We now check to see if we are writing file "inplace" */ if (inplace) { fd2 = do_open(fname, O_WRONLY|O_CREAT, 0); if (fd2 == -1) { rsyserr(FERROR, errno, "open %s failed", full_fname(fname)); discard_receive_data(f_in, file->length); if (fd1 != -1) close(fd1); continue; } } else { if (!get_tmpname(fnametmp,fname)) { discard_receive_data(f_in, file->length); if (fd1 != -1) close(fd1); continue; } /* we initially set the perms without the * setuid/setgid bits to ensure that there is no race * condition. They are then correctly updated after * the lchown. Thanks to [email protected] for pointing * this out. We also set it initially without group * access because of a similar race condition. */ fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); /* in most cases parent directories will already exist * because their information should have been previously * transferred, but that may not be the case with -R */ if (fd2 == -1 && relative_paths && errno == ENOENT && create_directory_path(fnametmp, orig_umask) == 0) { /* Get back to name with XXXXXX in it. */ get_tmpname(fnametmp, fname); fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); } if (fd2 == -1) { rsyserr(FERROR, errno, "mkstemp %s failed", full_fname(fnametmp)); discard_receive_data(f_in, file->length); if (fd1 != -1) close(fd1); continue; } if (partialptr) cleanup_set(fnametmp, partialptr, file, fd1, fd2); } /* log the transfer */ if (log_before_transfer) log_item(file, &initial_stats, iflags, NULL); else if (!am_server && verbose && do_progress) rprintf(FINFO, "%s\n", safe_fname(fname)); /* recv file data */ recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size, fname, fd2, file->length); if (!log_before_transfer) log_item(file, &initial_stats, iflags, NULL); if (fd1 != -1) close(fd1); if (close(fd2) < 0) { rsyserr(FERROR, errno, "close failed on %s", full_fname(fnametmp)); exit_cleanup(RERR_FILEIO); } if ((recv_ok && (!delay_updates || !partialptr)) || inplace) { finish_transfer(fname, fnametmp, file, recv_ok, 1); if (partialptr != fname && fnamecmp == partialptr) { do_unlink(partialptr); handle_partial_dir(partialptr, PDIR_DELETE); } } else if (keep_partial && partialptr && handle_partial_dir(partialptr, PDIR_CREATE)) { finish_transfer(partialptr, fnametmp, file, recv_ok, !partial_dir); if (delay_updates && recv_ok) { set_delayed_bit(i); recv_ok = -1; } } else { partialptr = NULL; do_unlink(fnametmp); } cleanup_disable(); if (recv_ok > 0) { if (remove_sent_files || (preserve_hard_links && file->link_u.links)) { SIVAL(numbuf, 0, i); send_msg(MSG_SUCCESS, numbuf, 4); } } else if (!recv_ok) { int msgtype = phase || read_batch ? FERROR : FINFO; if (msgtype == FERROR || verbose) { char *errstr, *redostr, *keptstr; if (!(keep_partial && partialptr) && !inplace) keptstr = "discarded"; else if (partial_dir) keptstr = "put into partial-dir"; else keptstr = "retained"; if (msgtype == FERROR) { errstr = "ERROR"; redostr = ""; } else { errstr = "WARNING"; redostr = " (will try again)"; } rprintf(msgtype, "%s: %s failed verification -- update %s%s.\n", errstr, safe_fname(fname), keptstr, redostr); } if (!phase) { SIVAL(numbuf, 0, i); send_msg(MSG_REDO, numbuf, 4); } } } make_backups = save_make_backups; if (phase == 2 && delay_updates) /* for protocol_version < 29 */ handle_delayed_updates(flist, local_name); if (verbose > 2) rprintf(FINFO,"recv_files finished\n"); return 0; }
void edit_room_field(room_t * QRedit, unsigned int forum_id, int fieldnum) { int loop, i, j = 0; char *quad_name; switch (fieldnum) { case '1': cprintf("%s%s%s%s", "\1rPlease keep length of name to under 36 characters.\n", "\1w ", "|------------------------------------|\n", "\1rEnter new quadrant name\1w: \1c"); quad_name = get_name(3); if (strlen(quad_name) < 1) { cprintf("\1gOk, name not changed.\n"); break; } if (get_room_number(quad_name) != -1) { cprintf("\1rThat name is already taken, sorry.\n"); } else { log_sysop_action("changed %ss name into %s.", QRedit->name, quad_name); strcpy(QRedit->name, quad_name); mono_sql_f_rename_forum(forum_id, quad_name); /* if we rename a guessname, up the generation no */ if ( QRedit->flags & QR_GUESSNAME ) QRedit->generation++; need_rewrite = TRUE; } break; /*-------------------------------------------------------------------*/ case '3': /* room type */ cprintf("\1g%s Type: \1w<\1r1\1w> \1gPublic \1w<\1r2\1w> \1rPrivate \1w: \1c", config.forum); loop = get_single("12"); if (loop == '1') { cprintf("\1g%s set to PUBLIC.\n\n", config.forum); QRedit->flags &= ~QR_PRIVATE; } else if (loop == '2') { cprintf("\1r%s set to INVITE ONLY.\n\n", config.forum); QRedit->flags |= QR_PRIVATE; cprintf("Kick out all users? "); if (yesno() == YES) { QRedit->generation++; if (QRedit->generation == 100) QRedit->generation = 10; if (invite(who_am_i(NULL), curr_rm) == -1) cprintf("Error inviting yourself.\n"); } } need_rewrite = TRUE; break; /*--------------------------------------------------------------------*/ case '4': cprintf("\1gPostType: \1w<\1y1\1w> \1gNormal \1w<\1y2\1w>\1pAnon-only \1w<\1y3\1w>\1pAnon-option \1w: \1c"); loop = get_single("123"); if (loop == '1') { /* normal room, remove flags */ QRedit->flags &= ~QR_ANONONLY; QRedit->flags &= ~QR_ANON2; } if (loop == '2') { /* anononly room, set & unset proper flags */ QRedit->flags |= QR_ANONONLY; QRedit->flags &= ~QR_ANON2; } if (loop == '3') { /* anonopt room */ QRedit->flags |= QR_ANON2; QRedit->flags &= ~QR_ANONONLY; } if (QRedit->flags & (QR_ANONONLY | QR_ANON2)) { cprintf("\1gShould the users be able to use Aliasnames? (y/n) "); if (yesno() == YES) QRedit->flags |= QR_ALIASNAME; else QRedit->flags &= ~QR_ALIASNAME; } else QRedit->flags &= ~QR_ALIASNAME; need_rewrite = TRUE; break; /*--------------------------------------------------------------------*/ case '5': QRedit->flags ^= QR_SUBJECTLINE; need_rewrite = TRUE; break; /*--------------------------------------------------------------------*/ case '6': QRedit->flags ^= QR_DESCRIBED; need_rewrite = TRUE; break; /*--------------------------------------------------------------------*/ case '7': QRedit->flags ^= QR_READONLY; need_rewrite = TRUE; break; /*--------------------------------------------------------------------*/ case '8': QRedit->flags ^= QR_NOZAP; need_rewrite = TRUE; break; /*--------------------------------------------------------------------*/ case '9': QRedit->flags ^= QR_INUSE; need_rewrite = TRUE; break; /*--------------------------------------------------------------------*/ case '0': QRedit->flags ^= QR_GUESSNAME; need_rewrite = TRUE; break; /*--------------------------------------------------------------------*/ case 'a': case 'A': cprintf("\1rEnter the new maximum number of messages\1w(\1r%d\1w): \1c", QRedit->maxmsg); j = qc_get_pos_int('\0', 4); if (j < 10) { cprintf("\1rDon't be daft! 10 messages is the minimum.\n"); break; } else if (j > 1000) { cprintf("\1rDon't be daft! 1000 messages is the maximum.\n"); break; } else { QRedit->maxmsg = j; need_rewrite = TRUE; break; } /*--------------------------------------------------------------------*/ case 'b': case 'B': cprintf("\1rEnter the new highest %s\1w: \1c", config.message); j = qc_get_pos_int('\0', 7); cprintf("\1f\1gAre you \1rSURE\1g you want to set the highest for `\1y%s\1g` to \1w%ld\1g? \1c", QRedit->name, j); if (yesno() == YES) { QRedit->highest = j; cprintf("\1gIf you say so... done.\n"); need_rewrite = TRUE; } break; /*--------------------------------------------------------------------*/ case 'c': case 'C': cprintf("\1rEnter the new lowest %s\1w: \1c", config.message); j = qc_get_pos_int('\0', 7); cprintf("\1f\1gAre you \1rSURE\1g you want to set the lowest for `\1y%s\1g` to \1w%ld\1g? \1c", QRedit->name, j); if (yesno() == YES) { QRedit->lowest = j; cprintf("\1gIf you say so... done.\n"); need_rewrite = TRUE; } break; /*--------------------------------------------------------------------*/ case 'd': case 'D': for (i = 0; i < CATEGORIES; i++) cprintf("\1w<\1r%2d\1w>\1g %s\n", i, fish[i]); cprintf("\1gEnter the new category number\1w: \1c"); if ((i = qc_get_pos_int('\0', 2)) < 0) break; else { if (i >= CATEGORIES) { cprintf("\n\1r+++ OUT OF CHEESE ERROR - REDO FROM START +++\n\n"); break; } else { strcpy(QRedit->category, fish[i]); need_rewrite = TRUE; break; } cprintf("\1r\1nUm, what?\n\n"); } break; /*--------------------------------------------------------------------*/ default: break; } /* end switch */ }
// Called when the user chooses the "Exit" menu item. void FeaturesUI::cb_exit(Fl_Menu_ *o, void *v) { who_am_i(o)->mainWindow->hide(); }
// Called when the user selects "Algorithm 2". void FeaturesUI::cb_match_algorithm_2(Fl_Menu_ *o, void *v) { who_am_i(o)->doc->set_match_algorithm(2); }
// Called when the user chooses the "Perform Query" menu item. void FeaturesUI::cb_perform_query(Fl_Menu_ *o, void *v) { who_am_i(o)->doc->perform_query(); }
/** * Eventually calls exit(), passing @p code, therefore does not return. * * @param code one of the RERR_* codes from errcode.h. **/ NORETURN void _exit_cleanup(int code, const char *file, int line) { static int switch_step = 0; static int exit_code = 0, exit_line = 0; static const char *exit_file = NULL; static int first_code = 0; SIGACTION(SIGUSR1, SIG_IGN); SIGACTION(SIGUSR2, SIG_IGN); if (!exit_code) { /* Preserve first error exit info when recursing. */ exit_code = code; exit_file = file; exit_line = line < 0 ? -line : line; } /* If this is the exit at the end of the run, the server side * should not attempt to output a message (see log_exit()). */ if (am_server && code == 0) am_server = 2; /* Some of our actions might cause a recursive call back here, so we * keep track of where we are in the cleanup and never repeat a step. */ switch (switch_step) { #include "case_N.h" /* case 0: */ switch_step++; first_code = code; if (output_needs_newline) { fputc('\n', stdout); output_needs_newline = 0; } if (DEBUG_GTE(EXIT, 2)) { rprintf(FINFO, "[%s] _exit_cleanup(code=%d, file=%s, line=%d): entered\n", who_am_i(), code, file, line); } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (cleanup_child_pid != -1) { int status; int pid = wait_process(cleanup_child_pid, &status, WNOHANG); if (pid == cleanup_child_pid) { status = WEXITSTATUS(status); if (status > exit_code) exit_code = status; } } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (cleanup_got_literal && (cleanup_fname || cleanup_fd_w != -1)) { if (cleanup_fd_r != -1) { close(cleanup_fd_r); cleanup_fd_r = -1; } if (cleanup_fd_w != -1) { flush_write_file(cleanup_fd_w); close(cleanup_fd_w); cleanup_fd_w = -1; } if (cleanup_fname && cleanup_new_fname && keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) { int tweak_modtime = 0; const char *fname = cleanup_fname; cleanup_fname = NULL; if (!partial_dir) { /* We don't want to leave a partial file with a modern time or it * could be skipped via --update. Setting the time to something * really old also helps it to stand out as unfinished in an ls. */ tweak_modtime = 1; cleanup_file->modtime = 0; } finish_transfer(cleanup_new_fname, fname, NULL, NULL, cleanup_file, tweak_modtime, !partial_dir); } } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (flush_ok_after_signal) { flush_ok_after_signal = False; if (code == RERR_SIGNAL) io_flush(FULL_FLUSH); } if (!exit_code && !code) io_flush(FULL_FLUSH); /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (cleanup_fname) do_unlink(cleanup_fname); if (exit_code) kill_all(SIGUSR1); if (cleanup_pid && cleanup_pid == getpid()) { char *pidf = lp_pid_file(); if (pidf && *pidf) unlink(lp_pid_file()); } if (exit_code == 0) { if (code) exit_code = code; if (io_error & IOERR_DEL_LIMIT) exit_code = RERR_DEL_LIMIT; if (io_error & IOERR_VANISHED) exit_code = RERR_VANISHED; if (io_error & IOERR_GENERAL || got_xfer_error) exit_code = RERR_PARTIAL; } /* If line < 0, this exit is after a MSG_ERROR_EXIT event, so * we don't want to output a duplicate error. */ if ((exit_code && line > 0) || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1)))) log_exit(exit_code, exit_file, exit_line); /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (DEBUG_GTE(EXIT, 1)) { rprintf(FINFO, "[%s] _exit_cleanup(code=%d, file=%s, line=%d): " "about to call exit(%d)\n", who_am_i(), first_code, exit_file, exit_line, exit_code); } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (exit_code && exit_code != RERR_SOCKETIO && exit_code != RERR_STREAMIO && exit_code != RERR_SIGNAL1 && exit_code != RERR_TIMEOUT && !shutting_down && (protocol_version >= 31 || am_receiver)) { if (line > 0) { if (DEBUG_GTE(EXIT, 3)) { rprintf(FINFO, "[%s] sending MSG_ERROR_EXIT with exit_code %d\n", who_am_i(), exit_code); } send_msg_int(MSG_ERROR_EXIT, exit_code); } noop_io_until_death(); } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (am_server && exit_code) msleep(100); close_all(); /* FALLTHROUGH */ default: break; } exit(exit_code); }
int read_ndx_and_attrs(int f_in, int f_out, int *iflag_ptr, uchar *type_ptr, char *buf, int *len_ptr) { int len, iflags = 0; struct file_list *flist; uchar fnamecmp_type = FNAMECMP_FNAME; int ndx; read_loop: while (1) { ndx = read_ndx(f_in); if (ndx >= 0) break; if (ndx == NDX_DONE) return ndx; if (ndx == NDX_DEL_STATS) { read_del_stats(f_in); if (am_sender && am_server) write_del_stats(f_out); continue; } if (!inc_recurse || am_sender) { int last; if (first_flist) last = first_flist->prev->ndx_start + first_flist->prev->used - 1; else last = -1; rprintf(FERROR, "Invalid file index: %d (%d - %d) [%s]\n", ndx, NDX_DONE, last, who_am_i()); exit_cleanup(RERR_PROTOCOL); } if (ndx == NDX_FLIST_EOF) { flist_eof = 1; if (DEBUG_GTE(FLIST, 3)) rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); write_int(f_out, NDX_FLIST_EOF); continue; } ndx = NDX_FLIST_OFFSET - ndx; if (ndx < 0 || ndx >= dir_flist->used) { ndx = NDX_FLIST_OFFSET - ndx; rprintf(FERROR, "Invalid dir index: %d (%d - %d) [%s]\n", ndx, NDX_FLIST_OFFSET, NDX_FLIST_OFFSET - dir_flist->used + 1, who_am_i()); exit_cleanup(RERR_PROTOCOL); } if (DEBUG_GTE(FLIST, 2)) { rprintf(FINFO, "[%s] receiving flist for dir %d\n", who_am_i(), ndx); } /* Send all the data we read for this flist to the generator. */ start_flist_forward(ndx); flist = recv_file_list(f_in); flist->parent_ndx = ndx; stop_flist_forward(); } iflags = protocol_version >= 29 ? read_shortint(f_in) : ITEM_TRANSFER | ITEM_MISSING_DATA; /* Support the protocol-29 keep-alive style. */ if (protocol_version < 30 && ndx == cur_flist->used && iflags == ITEM_IS_NEW) { if (am_sender) maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH); goto read_loop; } flist = flist_for_ndx(ndx, "read_ndx_and_attrs"); if (flist != cur_flist) { cur_flist = flist; if (am_sender) { file_old_total = cur_flist->used; for (flist = first_flist; flist != cur_flist; flist = flist->next) file_old_total += flist->used; } } if (iflags & ITEM_BASIS_TYPE_FOLLOWS) fnamecmp_type = read_byte(f_in); *type_ptr = fnamecmp_type; if (iflags & ITEM_XNAME_FOLLOWS) { if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0) exit_cleanup(RERR_PROTOCOL); } else { *buf = '\0'; len = -1; } *len_ptr = len; if (iflags & ITEM_TRANSFER) { int i = ndx - cur_flist->ndx_start; if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) { rprintf(FERROR, "received request to transfer non-regular file: %d [%s]\n", ndx, who_am_i()); exit_cleanup(RERR_PROTOCOL); } } *iflag_ptr = iflags; return ndx; }
NORETURN void overflow_exit(const char *str) { rprintf(FERROR, "ERROR: buffer overflow in %s [%s]\n", str, who_am_i()); exit_cleanup(RERR_MALLOC); }
void setup_iconv(void) { const char *defset = default_charset(); # ifdef ICONV_OPTION const char *charset; char *cp; # endif if (!am_server && !allow_8bit_chars) { /* It's OK if this fails... */ ic_chck = iconv_open(defset, defset); if (DEBUG_GTE(ICONV, 2)) { if (ic_chck == (iconv_t)-1) { rprintf(FINFO, "msg checking via isprint()" " (iconv_open(\"%s\", \"%s\") errno: %d)\n", defset, defset, errno); } else { rprintf(FINFO, "msg checking charset: %s\n", defset); } } } else ic_chck = (iconv_t)-1; # ifdef ICONV_OPTION if (!iconv_opt) return; if ((cp = strchr(iconv_opt, ',')) != NULL) { if (am_server) /* A local transfer needs this. */ iconv_opt = cp + 1; else *cp = '\0'; } if (!*iconv_opt || (*iconv_opt == '.' && iconv_opt[1] == '\0')) charset = defset; else charset = iconv_opt; if ((ic_send = iconv_open(UTF8_CHARSET, charset)) == (iconv_t)-1) { rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n", UTF8_CHARSET, charset); exit_cleanup(RERR_UNSUPPORTED); } if ((ic_recv = iconv_open(charset, UTF8_CHARSET)) == (iconv_t)-1) { rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n", charset, UTF8_CHARSET); exit_cleanup(RERR_UNSUPPORTED); } if (DEBUG_GTE(ICONV, 1)) { rprintf(FINFO, "[%s] charset: %s\n", who_am_i(), *charset ? charset : "[LOCALE]"); } # endif }
/** * main routine for receiver process. * * Receiver process runs on the same host as the generator process. */ int recv_files(int f_in, char *local_name) { int fd1,fd2; STRUCT_STAT st; int iflags, xlen; char *fname, fbuf[MAXPATHLEN]; char xname[MAXPATHLEN]; char fnametmp[MAXPATHLEN]; char *fnamecmp, *partialptr; char fnamecmpbuf[MAXPATHLEN]; uchar fnamecmp_type; struct file_struct *file; struct stats initial_stats; int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i; enum logcode log_code = log_before_transfer ? FLOG : FINFO; int max_phase = protocol_version >= 29 ? 2 : 1; int dflt_perms = (ACCESSPERMS & ~orig_umask); #ifdef SUPPORT_ACLS const char *parent_dirname = ""; #endif int ndx, recv_ok; if (verbose > 2) rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used); if (delay_updates) delayed_bits = bitbag_create(cur_flist->used + 1); while (1) { cleanup_disable(); /* This call also sets cur_flist. */ ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type, xname, &xlen); if (ndx == NDX_DONE) { if (inc_recurse && first_flist) { if (read_batch) gen_wants_ndx(first_flist->used + first_flist->ndx_start); flist_free(first_flist); if (first_flist) continue; } else if (read_batch && first_flist) gen_wants_ndx(first_flist->used); if (++phase > max_phase) break; if (verbose > 2) rprintf(FINFO, "recv_files phase=%d\n", phase); if (phase == 2 && delay_updates) handle_delayed_updates(local_name); send_msg(MSG_DONE, "", 0, 0); continue; } if (ndx - cur_flist->ndx_start >= 0) file = cur_flist->files[ndx - cur_flist->ndx_start]; else file = dir_flist->files[cur_flist->parent_ndx]; fname = local_name ? local_name : f_name(file, fbuf); if (verbose > 2) rprintf(FINFO, "recv_files(%s)\n", fname); #ifdef SUPPORT_XATTRS if (iflags & ITEM_REPORT_XATTR && !dry_run) recv_xattr_request(file, f_in); #endif if (!(iflags & ITEM_TRANSFER)) { maybe_log_item(file, iflags, itemizing, xname); #ifdef SUPPORT_XATTRS if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run) set_file_attrs(fname, file, NULL, fname, 0); #endif continue; } if (phase == 2) { rprintf(FERROR, "got transfer request in phase 2 [%s]\n", who_am_i()); exit_cleanup(RERR_PROTOCOL); } if (file->flags & FLAG_FILE_SENT) { if (csum_length == SHORT_SUM_LENGTH) { if (keep_partial && !partial_dir) make_backups = -make_backups; /* prevents double backup */ if (append_mode) sparse_files = -sparse_files; append_mode = -append_mode; csum_length = SUM_LENGTH; redoing = 1; } } else { if (csum_length != SHORT_SUM_LENGTH) { if (keep_partial && !partial_dir) make_backups = -make_backups; if (append_mode) sparse_files = -sparse_files; append_mode = -append_mode; csum_length = SHORT_SUM_LENGTH; redoing = 0; } } if (!am_server && do_progress) set_current_file_index(file, ndx); stats.num_transferred_files++; stats.total_transferred_size += F_LENGTH(file); cleanup_got_literal = 0; if (daemon_filter_list.head && check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) { rprintf(FERROR, "attempt to hack rsync failed.\n"); exit_cleanup(RERR_PROTOCOL); } if (!do_xfers) { /* log the transfer */ log_item(FCLIENT, file, &stats, iflags, NULL); if (read_batch) discard_receive_data(f_in, F_LENGTH(file)); continue; } if (write_batch < 0) { log_item(FCLIENT, file, &stats, iflags, NULL); if (!am_server) discard_receive_data(f_in, F_LENGTH(file)); continue; } if (read_batch) { if (!(redoing ? we_want_redo(ndx) : gen_wants_ndx(ndx))) { rprintf(FINFO, "(Skipping batched update for%s \"%s\")\n", redoing ? " resend of" : "", fname); discard_receive_data(f_in, F_LENGTH(file)); file->flags |= FLAG_FILE_SENT; continue; } } partialptr = partial_dir ? partial_dir_fname(fname) : fname; if (protocol_version >= 29) { switch (fnamecmp_type) { case FNAMECMP_FNAME: fnamecmp = fname; break; case FNAMECMP_PARTIAL_DIR: fnamecmp = partialptr; break; case FNAMECMP_BACKUP: fnamecmp = get_backup_name(fname); break; case FNAMECMP_FUZZY: if (file->dirname) { pathjoin(fnamecmpbuf, MAXPATHLEN, file->dirname, xname); fnamecmp = fnamecmpbuf; } else fnamecmp = xname; break; default: if (fnamecmp_type >= basis_dir_cnt) { rprintf(FERROR, "invalid basis_dir index: %d.\n", fnamecmp_type); exit_cleanup(RERR_PROTOCOL); } pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], fname); fnamecmp = fnamecmpbuf; break; } if (!fnamecmp || (daemon_filter_list.head && check_filter(&daemon_filter_list, FLOG, fname, 0) < 0)) { fnamecmp = fname; fnamecmp_type = FNAMECMP_FNAME; } } else { /* Reminder: --inplace && --partial-dir are never * enabled at the same time. */ if (inplace && make_backups > 0) { if (!(fnamecmp = get_backup_name(fname))) fnamecmp = fname; else fnamecmp_type = FNAMECMP_BACKUP; } else if (partial_dir && partialptr) fnamecmp = partialptr; else fnamecmp = fname; } initial_stats = stats; /* open the file */ fd1 = do_open(fnamecmp, O_RDONLY, 0); if (fd1 == -1 && protocol_version < 29) { if (fnamecmp != fname) { fnamecmp = fname; fd1 = do_open(fnamecmp, O_RDONLY, 0); } if (fd1 == -1 && basis_dir[0]) { /* pre-29 allowed only one alternate basis */ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[0], fname); fnamecmp = fnamecmpbuf; fd1 = do_open(fnamecmp, O_RDONLY, 0); } } updating_basis_or_equiv = inplace && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP); if (fd1 == -1) { st.st_mode = 0; st.st_size = 0; } else if (do_fstat(fd1,&st) != 0) { rsyserr(FERROR_XFER, errno, "fstat %s failed", full_fname(fnamecmp)); discard_receive_data(f_in, F_LENGTH(file)); close(fd1); if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); continue; } if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) { /* this special handling for directories * wouldn't be necessary if robust_rename() * and the underlying robust_unlink could cope * with directories */ rprintf(FERROR_XFER, "recv_files: %s is a directory\n", full_fname(fnamecmp)); discard_receive_data(f_in, F_LENGTH(file)); close(fd1); if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); continue; } if (fd1 != -1 && !S_ISREG(st.st_mode)) { close(fd1); fd1 = -1; } /* If we're not preserving permissions, change the file-list's * mode based on the local permissions and some heuristics. */ if (!preserve_perms) { int exists = fd1 != -1; #ifdef SUPPORT_ACLS const char *dn = file->dirname ? file->dirname : "."; if (parent_dirname != dn && strcmp(parent_dirname, dn) != 0) { dflt_perms = default_perms_for_dir(dn); parent_dirname = dn; } #endif file->mode = dest_mode(file->mode, st.st_mode, dflt_perms, exists); } /* We now check to see if we are writing the file "inplace" */ if (inplace) { fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600); if (fd2 == -1) { rsyserr(FERROR_XFER, errno, "open %s failed", full_fname(fname)); } } else { fd2 = open_tmpfile(fnametmp, fname, file); if (fd2 != -1) cleanup_set(fnametmp, partialptr, file, fd1, fd2); } if (fd2 == -1) { discard_receive_data(f_in, F_LENGTH(file)); if (fd1 != -1) close(fd1); if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); continue; } /* log the transfer */ if (log_before_transfer) log_item(FCLIENT, file, &initial_stats, iflags, NULL); else if (!am_server && verbose && do_progress) rprintf(FINFO, "%s\n", fname); /* recv file data */ recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size, fname, fd2, F_LENGTH(file)); log_item(log_code, file, &initial_stats, iflags, NULL); if (fd1 != -1) close(fd1); if (close(fd2) < 0) { rsyserr(FERROR, errno, "close failed on %s", full_fname(fnametmp)); exit_cleanup(RERR_FILEIO); } if ((recv_ok && (!delay_updates || !partialptr)) || inplace) { if (partialptr == fname) partialptr = NULL; if (!finish_transfer(fname, fnametmp, fnamecmp, partialptr, file, recv_ok, 1)) recv_ok = -1; else if (fnamecmp == partialptr) { do_unlink(partialptr); handle_partial_dir(partialptr, PDIR_DELETE); } } else if (keep_partial && partialptr) { if (!handle_partial_dir(partialptr, PDIR_CREATE)) { rprintf(FERROR, "Unable to create partial-dir for %s -- discarding %s.\n", local_name ? local_name : f_name(file, NULL), recv_ok ? "completed file" : "partial file"); do_unlink(fnametmp); recv_ok = -1; } else if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL, file, recv_ok, !partial_dir)) recv_ok = -1; else if (delay_updates && recv_ok) { bitbag_set_bit(delayed_bits, ndx); recv_ok = 2; } else partialptr = NULL; } else do_unlink(fnametmp); cleanup_disable(); if (read_batch) file->flags |= FLAG_FILE_SENT; switch (recv_ok) { case 2: break; case 1: if (remove_source_files || inc_recurse || (preserve_hard_links && F_IS_HLINKED(file))) send_msg_int(MSG_SUCCESS, ndx); break; case 0: { enum logcode msgtype = redoing ? FERROR_XFER : FWARNING; if (msgtype == FERROR_XFER || verbose) { char *errstr, *redostr, *keptstr; if (!(keep_partial && partialptr) && !inplace) keptstr = "discarded"; else if (partial_dir) keptstr = "put into partial-dir"; else keptstr = "retained"; if (msgtype == FERROR_XFER) { errstr = "ERROR"; redostr = ""; } else { errstr = "WARNING"; redostr = read_batch ? " (may try again)" : " (will try again)"; } rprintf(msgtype, "%s: %s failed verification -- update %s%s.\n", errstr, local_name ? f_name(file, NULL) : fname, keptstr, redostr); } if (!redoing) { if (read_batch) flist_ndx_push(&batch_redo_list, ndx); send_msg_int(MSG_REDO, ndx); file->flags |= FLAG_FILE_SENT; } else if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); break; } case -1: if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); break; } } if (make_backups < 0) make_backups = -make_backups; if (phase == 2 && delay_updates) /* for protocol_version < 29 */ handle_delayed_updates(local_name); if (verbose > 2) rprintf(FINFO,"recv_files finished\n"); return 0; }
/** * main routine for receiver process. * * Receiver process runs on the same host as the generator process. */ int recv_files(int f_in, char *local_name) { int fd1,fd2; STRUCT_STAT st; int iflags, xlen; char *fname, fbuf[MAXPATHLEN]; char xname[MAXPATHLEN]; char fnametmp[MAXPATHLEN]; char *fnamecmp, *partialptr; char fnamecmpbuf[MAXPATHLEN]; uchar fnamecmp_type; struct file_struct *file; struct stats initial_stats; int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i; enum logcode log_code = log_before_transfer ? FLOG : FINFO; int max_phase = protocol_version >= 29 ? 2 : 1; int dflt_perms = (ACCESSPERMS & ~orig_umask); #if 0 /* was SUPPORT_ACLS */ const char *parent_dirname = ""; #endif int ndx, recv_ok; if (verbose > 2) rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used); if (delay_updates) delayed_bits = bitbag_create(cur_flist->used + 1); while (1) { struct sum_struct sum; int numMatchTokens = -1, nextToken = 0; char *nextData = NULL; static char file_sum[MAX_DIGEST_LEN]; cleanup_disable(); /* This call also sets cur_flist. */ ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type, xname, &xlen); if (ndx == NDX_DONE) { if (inc_recurse && first_flist) { if (read_batch) gen_wants_ndx(first_flist->used + first_flist->ndx_start); flist_free(first_flist); if (first_flist) continue; } else if (read_batch && first_flist) gen_wants_ndx(first_flist->used); if (++phase > max_phase) break; if (verbose > 2) rprintf(FINFO, "recv_files phase=%d\n", phase); if (phase == 2 && delay_updates) handle_delayed_updates(local_name); send_msg(MSG_DONE, "", 0, 0); continue; } if (ndx - cur_flist->ndx_start >= 0) file = cur_flist->files[ndx - cur_flist->ndx_start]; else file = dir_flist->files[cur_flist->parent_ndx]; fname = local_name ? local_name : f_name(file, fbuf); if (verbose > 2) rprintf(FINFO, "recv_files(%s)\n", fname); #ifdef SUPPORT_XATTRS if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers) recv_xattr_request(file, f_in); #endif if (!(iflags & ITEM_TRANSFER)) { maybe_log_item(file, iflags, itemizing, xname); #ifdef SUPPORT_XATTRS if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers && !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)) set_file_attrs(fname, file, NULL, fname, 0); #endif continue; } if (phase == 2) { rprintf(FERROR, "got transfer request in phase 2 [%s]\n", who_am_i()); exit_cleanup(RERR_PROTOCOL); } if (file->flags & FLAG_FILE_SENT) { if (csum_length == SHORT_SUM_LENGTH) { if (keep_partial && !partial_dir) make_backups = -make_backups; /* prevents double backup */ if (append_mode) sparse_files = -sparse_files; append_mode = -append_mode; csum_length = SUM_LENGTH; redoing = 1; } } else { if (csum_length != SHORT_SUM_LENGTH) { if (keep_partial && !partial_dir) make_backups = -make_backups; if (append_mode) sparse_files = -sparse_files; append_mode = -append_mode; csum_length = SHORT_SUM_LENGTH; redoing = 0; } } if (!am_server && do_progress) set_current_file_index(file, ndx); stats.num_transferred_files++; stats.total_transferred_size += F_LENGTH(file); cleanup_got_literal = 0; if (daemon_filter_list.head && check_filter(&daemon_filter_list, FLOG, fname, 0) < 0) { rprintf(FERROR, "attempt to hack rsync failed.\n"); exit_cleanup(RERR_PROTOCOL); } read_sum_head(f_in, &sum); if (read_batch) { int wanted = redoing ? we_want_redo(ndx) : gen_wants_ndx(ndx); if (!wanted) { rprintf(FINFO, "(Skipping batched update for%s \"%s\")\n", redoing ? " resend of" : "", fname); discard_receive_data(f_in, F_LENGTH(file), &sum, numMatchTokens, nextToken, nextData, file_sum); file->flags |= FLAG_FILE_SENT; continue; } } if (!do_xfers) { /* log the transfer */ log_item(FCLIENT, file, &stats, iflags, NULL); if (read_batch) discard_receive_data(f_in, F_LENGTH(file), &sum, numMatchTokens, nextToken, nextData, file_sum); continue; } if (write_batch < 0) { log_item(FCLIENT, file, &stats, iflags, NULL); if (!am_server) discard_receive_data(f_in, F_LENGTH(file), &sum, numMatchTokens, nextToken, nextData, file_sum); continue; } partialptr = partial_dir ? partial_dir_fname(fname) : fname; if (protocol_version >= 29) { switch (fnamecmp_type) { case FNAMECMP_FNAME: fnamecmp = fname; break; case FNAMECMP_PARTIAL_DIR: fnamecmp = partialptr; break; case FNAMECMP_BACKUP: fnamecmp = get_backup_name(fname); break; case FNAMECMP_FUZZY: if (file->dirname) { pathjoin(fnamecmpbuf, MAXPATHLEN, file->dirname, xname); fnamecmp = fnamecmpbuf; } else fnamecmp = xname; break; default: if (fnamecmp_type >= basis_dir_cnt) { rprintf(FERROR, "invalid basis_dir index: %d.\n", fnamecmp_type); exit_cleanup(RERR_PROTOCOL); } pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], fname); fnamecmp = fnamecmpbuf; break; } if (!fnamecmp || (daemon_filter_list.head && check_filter(&daemon_filter_list, FLOG, fname, 0) < 0)) { fnamecmp = fname; fnamecmp_type = FNAMECMP_FNAME; } } else { /* Reminder: --inplace && --partial-dir are never * enabled at the same time. */ if (inplace && make_backups > 0) { if (!(fnamecmp = get_backup_name(fname))) fnamecmp = fname; else fnamecmp_type = FNAMECMP_BACKUP; } else if (partial_dir && partialptr) fnamecmp = partialptr; else fnamecmp = fname; } initial_stats = stats; /* * Opening/reading/writing files in BackupPC is quite expensive, given the * compression. Before we open the file and call mkstemp, we peek ahead at * the delta tokens to see if the file is unchanged. If so, we skip the file * open, mkstemp and writing. The file is unchanged if the tokens * are sequential matching block numbers, which are encoded as * negative integers (ie: -1, -2, -3...), with no literal data * tokens (which have positive numbers). * * If the file has changed, at some point a matching block token * will be out of order, or we will encounter a literal data token. * At that point, we stop reading ahead and proceed as normal. * We pass the number of matching block tokens, and the first * unexpected token, to receive_data(), so it can process all * the tokens back (basically playing them back). * * Of course, this only applies if the file exists already, * and protocol_version 30 is required since older protocols * use MD4 for the full-file digest, not MD5. * * First we need to read the sum struct, then start reading the * tokens. */ recv_ok = 0; if ( protocol_version >= 30 ) { numMatchTokens = 0; while ( (nextToken = recv_token(f_in, &nextData)) != 0 ) { if ( nextToken != -numMatchTokens - 1 ) break; numMatchTokens++; } if ( nextToken == 0 ) { OFF_T flength = (OFF_T)numMatchTokens * sum.blength; if ( sum.remainder && numMatchTokens > 0 ) flength -= sum.blength - sum.remainder; /* * Likely exact match - read the final file digest and make * sure the digest and file size match the existing file. * If so, this call creates the temporary file so the * attributes can be checked/set, and then renamed as * before. */ read_buf(f_in, file_sum, MD5_DIGEST_LEN); if ( !bpc_sysCall_checkFileMatch(fnamecmp, fnametmp, file, file_sum, flength) ) { recv_ok = 1; if ( log_before_transfer ) { iflags &= ~ITEM_REPORT_CHANGE; log_item(FCLIENT, file, &initial_stats, iflags, NULL); } } } } if ( !recv_ok ) { /* * proceed as normal, remembering to replay the tokens we read ahead above: * first, numMatchTokens: -1, -2, ..., -numMatchTokens, * then (nextToken,nextData). After that we go back to reading the * remaining tokens from f_in. */ /* open the file */ fd1 = do_open(fnamecmp, O_RDONLY, 0); if ( fd1 < 0 && protocol_version >= 30 && always_checksum ) { /* * For protocol_version >= 30 and if always_checksum is set, we can use the * MD5 whole-file digest to check for a potential match via the pool. * Use that as the basis if the file is there. The generator does * the same in recv_generator(). */ if ( S_ISREG(file->mode) && !bpc_sysCall_poolFileCheck(fnamecmp, file) ) { fd1 = do_open(fnamecmp, O_RDONLY, 0); } } if (fd1 == -1 && protocol_version < 29) { if (fnamecmp != fname) { fnamecmp = fname; fd1 = do_open(fnamecmp, O_RDONLY, 0); } if (fd1 == -1 && basis_dir[0]) { /* pre-29 allowed only one alternate basis */ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[0], fname); fnamecmp = fnamecmpbuf; fd1 = do_open(fnamecmp, O_RDONLY, 0); } } updating_basis_or_equiv = inplace && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP); if (fd1 == -1) { st.st_mode = 0; st.st_size = 0; } else if (do_fstat(fd1,&st) != 0) { rsyserr(FERROR_XFER, errno, "fstat %s failed", full_fname(fnamecmp)); discard_receive_data(f_in, F_LENGTH(file), &sum, numMatchTokens, nextToken, nextData, file_sum); bpc_close(fd1); if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); continue; } if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) { /* this special handling for directories * wouldn't be necessary if robust_rename() * and the underlying robust_unlink could cope * with directories */ rprintf(FERROR_XFER, "recv_files: %s is a directory\n", full_fname(fnamecmp)); discard_receive_data(f_in, F_LENGTH(file), &sum, numMatchTokens, nextToken, nextData, file_sum); bpc_close(fd1); if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); continue; } if (fd1 != -1 && !S_ISREG(st.st_mode)) { bpc_close(fd1); fd1 = -1; } /* If we're not preserving permissions, change the file-list's * mode based on the local permissions and some heuristics. */ if (!preserve_perms) { int exists = fd1 != -1; #if 0 /* was SUPPORT_ACLS */ const char *dn = file->dirname ? file->dirname : "."; if (parent_dirname != dn && strcmp(parent_dirname, dn) != 0) { dflt_perms = default_perms_for_dir(dn); parent_dirname = dn; } #endif file->mode = dest_mode(file->mode, st.st_mode, dflt_perms, exists); } /* We now check to see if we are writing the file "inplace" */ if (inplace) { fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600); if (fd2 == -1) { rsyserr(FERROR_XFER, errno, "open %s failed", full_fname(fname)); } } else { fd2 = open_tmpfile(fnametmp, fname, file); if (fd2 != -1) cleanup_set(fnametmp, partialptr, file, fd1, fd2); } if (fd2 == -1) { discard_receive_data(f_in, F_LENGTH(file), &sum, numMatchTokens, nextToken, nextData, file_sum); if (fd1 != -1) bpc_close(fd1); if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); continue; } /* log the transfer */ if (log_before_transfer) log_item(FCLIENT, file, &initial_stats, iflags, NULL); else if (!am_server && verbose && do_progress) rprintf(FINFO, "%s\n", fname); /* recv file data */ recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size, fname, fd2, F_LENGTH(file), &sum, numMatchTokens, nextToken, nextData, file_sum); if (fd1 != -1) bpc_close(fd1); if (bpc_close(fd2) < 0) { rsyserr(FERROR, errno, "close failed on %s", full_fname(fnametmp)); exit_cleanup(RERR_FILEIO); } } log_item(log_code, file, &initial_stats, iflags, NULL); if ((recv_ok && (!delay_updates || !partialptr)) || inplace) { if (partialptr == fname) partialptr = NULL; if (!finish_transfer(fname, fnametmp, fnamecmp, partialptr, file, recv_ok, 1)) recv_ok = -1; else if (fnamecmp == partialptr) { do_unlink(partialptr); handle_partial_dir(partialptr, PDIR_DELETE); } } else if (keep_partial && partialptr) { if (!handle_partial_dir(partialptr, PDIR_CREATE)) { rprintf(FERROR, "Unable to create partial-dir for %s -- discarding %s.\n", local_name ? local_name : f_name(file, NULL), recv_ok ? "completed file" : "partial file"); do_unlink(fnametmp); recv_ok = -1; } else if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL, file, recv_ok, !partial_dir)) recv_ok = -1; else if (delay_updates && recv_ok) { bitbag_set_bit(delayed_bits, ndx); recv_ok = 2; } else partialptr = NULL; } else do_unlink(fnametmp); cleanup_disable(); if (read_batch) file->flags |= FLAG_FILE_SENT; switch (recv_ok) { case 2: break; case 1: if (remove_source_files || inc_recurse || (preserve_hard_links && F_IS_HLINKED(file))) send_msg_int(MSG_SUCCESS, ndx); break; case 0: { enum logcode msgtype = redoing ? FERROR_XFER : FWARNING; if (msgtype == FERROR_XFER || verbose) { char *errstr, *redostr, *keptstr; if (!(keep_partial && partialptr) && !inplace) keptstr = "discarded"; else if (partial_dir) keptstr = "put into partial-dir"; else keptstr = "retained"; if (msgtype == FERROR_XFER) { errstr = "ERROR"; redostr = ""; } else { errstr = "WARNING"; redostr = read_batch ? " (may try again)" : " (will try again)"; } rprintf(msgtype, "%s: %s failed verification -- update %s%s.\n", errstr, local_name ? f_name(file, NULL) : fname, keptstr, redostr); } if (!redoing) { if (read_batch) flist_ndx_push(&batch_redo_list, ndx); send_msg_int(MSG_REDO, ndx); file->flags |= FLAG_FILE_SENT; bpc_sysCall_printfileStatus(fname, "retry"); } else if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); bpc_sysCall_printfileStatus(fname, "fail"); break; } case -1: if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); break; } } if (make_backups < 0) make_backups = -make_backups; if (phase == 2 && delay_updates) /* for protocol_version < 29 */ handle_delayed_updates(local_name); if (verbose > 2) rprintf(FINFO,"recv_files finished\n"); return 0; }
/** * Eventually calls exit(), passing @p code, therefore does not return. * * @param code one of the RERR_* codes from errcode.h. **/ NORETURN void _exit_cleanup(int code, const char *file, int line) { static int switch_step = 0; static int exit_code = 0, exit_line = 0; static const char *exit_file = NULL; static int unmodified_code = 0; SIGACTION(SIGUSR1, SIG_IGN); SIGACTION(SIGUSR2, SIG_IGN); if (exit_code) { /* Preserve first exit info when recursing. */ code = exit_code; file = exit_file; line = exit_line; } /* If this is the exit at the end of the run, the server side * should not attempt to output a message (see log_exit()). */ if (am_server && code == 0) am_server = 2; /* Some of our actions might cause a recursive call back here, so we * keep track of where we are in the cleanup and never repeat a step. */ switch (switch_step) { #include "case_N.h" /* case 0: */ switch_step++; exit_code = unmodified_code = code; exit_file = file; exit_line = line; if (verbose > 3) { rprintf(FINFO, "[%s] _exit_cleanup(code=%d, file=%s, line=%d): entered\n", who_am_i(), code, file, line); } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (cleanup_child_pid != -1) { int status; int pid = wait_process(cleanup_child_pid, &status, WNOHANG); if (pid == cleanup_child_pid) { status = WEXITSTATUS(status); if (status > code) code = exit_code = status; } } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (cleanup_got_literal && cleanup_fname && cleanup_new_fname && keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) { const char *fname = cleanup_fname; cleanup_fname = NULL; if (cleanup_fd_r != -1) bpc_close(cleanup_fd_r); if (cleanup_fd_w != -1) { flush_write_file(cleanup_fd_w); bpc_close(cleanup_fd_w); } finish_transfer(cleanup_new_fname, fname, NULL, NULL, cleanup_file, 0, !partial_dir); } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (!code || am_server || am_receiver) io_flush(FULL_FLUSH); /* FALLTHROUGH */ #include "case_N.h" switch_step++; bpc_sysCall_cleanup(); if (cleanup_fname) do_unlink(cleanup_fname); if (code) kill_all(SIGUSR1); if (cleanup_pid && cleanup_pid == getpid()) { char *pidf = lp_pid_file(); if (pidf && *pidf) unlink(lp_pid_file()); } if (code == 0) { if (io_error & IOERR_DEL_LIMIT) code = exit_code = RERR_DEL_LIMIT; if (io_error & IOERR_VANISHED) code = exit_code = RERR_VANISHED; if (io_error & IOERR_GENERAL || got_xfer_error) code = exit_code = RERR_PARTIAL; } if (code || am_daemon || (logfile_name && (am_server || !verbose))) log_exit(code, file, line); /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (verbose > 2) { rprintf(FINFO, "[%s] _exit_cleanup(code=%d, file=%s, line=%d): " "about to call exit(%d)\n", who_am_i(), unmodified_code, file, line, code); } /* FALLTHROUGH */ #include "case_N.h" switch_step++; if (am_server && code) msleep(100); close_all(); /* FALLTHROUGH */ default: break; } exit(code); }
// Called when the user chooses the "Deselect All Features" menu item. void FeaturesUI::cb_deselect_all_features(Fl_Menu_ *o, void *v) { who_am_i(o)->doc->deselect_all_query_features(); }