示例#1
0
文件: server.c 项目: dong1/testsize
static void
crash_handler (int signo, siginfo_t * siginfo, void *dummyp)
{
  int pid;

  if (signo != SIGABRT && siginfo != NULL && siginfo->si_code <= 0)
    {
      register_fatal_signal_handler (signo);
      return;
    }

  if (os_set_signal_handler (signo, SIG_DFL) == SIG_ERR)
    {
      return;
    }

  if (!BO_IS_SERVER_RESTARTED () || !PRM_AUTO_RESTART_SERVER)
    {
      return;
    }

  pid = fork ();
  if (pid == 0)
    {
      char *installed_path;
      char err_log[PATH_MAX];
      int ppid;
      int fd, fd_max;

      fd_max = css_get_max_socket_fds ();

      for (fd = 3; fd < fd_max; fd++)
	{
	  close (fd);
	}

      ppid = getppid ();
      while (1)
	{
	  if (kill (ppid, 0) < 0)
	    {
	      break;
	    }
	  sleep (1);
	}

      unmask_signal (signo);

      if (PRM_ER_LOG_FILE != NULL)
	{
	  snprintf (err_log, PATH_MAX, "%s.%d", PRM_ER_LOG_FILE, ppid);
	  rename (PRM_ER_LOG_FILE, err_log);
	}

      execl (executable_path, executable_path, database_name, NULL);
      exit (0);
    }
}
示例#2
0
static int curl_download_internal(struct dload_payload *payload,
		const char *localpath, char **final_file, char **final_url)
{
	int ret = -1;
	FILE *localf = NULL;
	char *effective_url;
	char hostname[HOSTNAME_SIZE];
	char error_buffer[CURL_ERROR_SIZE] = {0};
	struct stat st;
	long timecond, remote_time = -1;
	double remote_size, bytes_dl;
	struct sigaction orig_sig_pipe, orig_sig_int;
	/* shortcut to our handle within the payload */
	alpm_handle_t *handle = payload->handle;
	CURL *curl = get_libcurl_handle(handle);
	handle->pm_errno = 0;

	/* make sure these are NULL */
	FREE(payload->tempfile_name);
	FREE(payload->destfile_name);
	FREE(payload->content_disp_name);

	payload->tempfile_openmode = "wb";
	if(!payload->remote_name) {
		STRDUP(payload->remote_name, get_filename(payload->fileurl),
				RET_ERR(handle, ALPM_ERR_MEMORY, -1));
	}
	if(curl_gethost(payload->fileurl, hostname, sizeof(hostname)) != 0) {
		_alpm_log(handle, ALPM_LOG_ERROR, _("url '%s' is invalid\n"), payload->fileurl);
		RET_ERR(handle, ALPM_ERR_SERVER_BAD_URL, -1);
	}

	if(payload->remote_name && strlen(payload->remote_name) > 0 &&
			strcmp(payload->remote_name, ".sig") != 0) {
		payload->destfile_name = get_fullpath(localpath, payload->remote_name, "");
		payload->tempfile_name = get_fullpath(localpath, payload->remote_name, ".part");
		if(!payload->destfile_name || !payload->tempfile_name) {
			goto cleanup;
		}
	} else {
		/* URL doesn't contain a filename, so make a tempfile. We can't support
		 * resuming this kind of download; partial transfers will be destroyed */
		payload->unlink_on_fail = 1;

		localf = create_tempfile(payload, localpath);
		if(localf == NULL) {
			goto cleanup;
		}
	}

	curl_set_handle_opts(payload, curl, error_buffer);

	if(localf == NULL) {
		localf = fopen(payload->tempfile_name, payload->tempfile_openmode);
		if(localf == NULL) {
			handle->pm_errno = ALPM_ERR_RETRIEVE;
			_alpm_log(handle, ALPM_LOG_ERROR,
					_("could not open file %s: %s\n"),
					payload->tempfile_name, strerror(errno));
			goto cleanup;
		}
	}

	_alpm_log(handle, ALPM_LOG_DEBUG,
			"opened tempfile for download: %s (%s)\n", payload->tempfile_name,
			payload->tempfile_openmode);

	curl_easy_setopt(curl, CURLOPT_WRITEDATA, localf);

	/* Ignore any SIGPIPE signals. With libcurl, these shouldn't be happening,
	 * but better safe than sorry. Store the old signal handler first. */
	mask_signal(SIGPIPE, SIG_IGN, &orig_sig_pipe);
	mask_signal(SIGINT, &inthandler, &orig_sig_int);

	/* perform transfer */
	payload->curlerr = curl_easy_perform(curl);
	_alpm_log(handle, ALPM_LOG_DEBUG, "curl returned error %d from transfer\n",
			payload->curlerr);

	/* disconnect relationships from the curl handle for things that might go out
	 * of scope, but could still be touched on connection teardown.  This really
	 * only applies to FTP transfers. */
	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, (char *)NULL);

	/* was it a success? */
	switch(payload->curlerr) {
		case CURLE_OK:
			/* get http/ftp response code */
			_alpm_log(handle, ALPM_LOG_DEBUG, "response code: %ld\n", payload->respcode);
			if(payload->respcode >= 400) {
				payload->unlink_on_fail = 1;
				/* non-translated message is same as libcurl */
				snprintf(error_buffer, sizeof(error_buffer),
						"The requested URL returned error: %ld", payload->respcode);
				_alpm_log(handle, ALPM_LOG_ERROR,
						_("failed retrieving file '%s' from %s : %s\n"),
						payload->remote_name, hostname, error_buffer);
				goto cleanup;
			}
			break;
		case CURLE_ABORTED_BY_CALLBACK:
			/* handle the interrupt accordingly */
			if(dload_interrupted == ABORT_OVER_MAXFILESIZE) {
				payload->curlerr = CURLE_FILESIZE_EXCEEDED;
				handle->pm_errno = ALPM_ERR_LIBCURL;
				/* use the 'size exceeded' message from libcurl */
				_alpm_log(handle, ALPM_LOG_ERROR,
						_("failed retrieving file '%s' from %s : %s\n"),
						payload->remote_name, hostname,
						curl_easy_strerror(CURLE_FILESIZE_EXCEEDED));
			}
			goto cleanup;
		default:
			/* delete zero length downloads */
			if(fstat(fileno(localf), &st) == 0 && st.st_size == 0) {
				payload->unlink_on_fail = 1;
			}
			if(!payload->errors_ok) {
				handle->pm_errno = ALPM_ERR_LIBCURL;
				_alpm_log(handle, ALPM_LOG_ERROR,
						_("failed retrieving file '%s' from %s : %s\n"),
						payload->remote_name, hostname, error_buffer);
			} else {
				_alpm_log(handle, ALPM_LOG_DEBUG,
						"failed retrieving file '%s' from %s : %s\n",
						payload->remote_name, hostname, error_buffer);
			}
			goto cleanup;
	}

	/* retrieve info about the state of the transfer */
	curl_easy_getinfo(curl, CURLINFO_FILETIME, &remote_time);
	curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &remote_size);
	curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &bytes_dl);
	curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &timecond);
	curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);

	if(final_url != NULL) {
		*final_url = effective_url;
	}

	/* time condition was met and we didn't download anything. we need to
	 * clean up the 0 byte .part file that's left behind. */
	if(timecond == 1 && DOUBLE_EQ(bytes_dl, 0)) {
		_alpm_log(handle, ALPM_LOG_DEBUG, "file met time condition\n");
		ret = 1;
		unlink(payload->tempfile_name);
		goto cleanup;
	}

	/* remote_size isn't necessarily the full size of the file, just what the
	 * server reported as remaining to download. compare it to what curl reported
	 * as actually being transferred during curl_easy_perform() */
	if(!DOUBLE_EQ(remote_size, -1) && !DOUBLE_EQ(bytes_dl, -1) &&
			!DOUBLE_EQ(bytes_dl, remote_size)) {
		handle->pm_errno = ALPM_ERR_RETRIEVE;
		_alpm_log(handle, ALPM_LOG_ERROR, _("%s appears to be truncated: %jd/%jd bytes\n"),
				payload->remote_name, (intmax_t)bytes_dl, (intmax_t)remote_size);
		goto cleanup;
	}

	if (payload->trust_remote_name) {
		if(payload->content_disp_name) {
			/* content-disposition header has a better name for our file */
			free(payload->destfile_name);
			payload->destfile_name = get_fullpath(localpath, payload->content_disp_name, "");
		} else {
			const char *effective_filename = strrchr(effective_url, '/');
			if(effective_filename && strlen(effective_filename) > 2) {
				effective_filename++;

				/* if destfile was never set, we wrote to a tempfile. even if destfile is
				 * set, we may have followed some redirects and the effective url may
				 * have a better suggestion as to what to name our file. in either case,
				 * refactor destfile to this newly derived name. */
				if(!payload->destfile_name || strcmp(effective_filename,
							strrchr(payload->destfile_name, '/') + 1) != 0) {
					free(payload->destfile_name);
					payload->destfile_name = get_fullpath(localpath, effective_filename, "");
				}
			}
		}
	}

	ret = 0;

cleanup:
	if(localf != NULL) {
		fclose(localf);
		utimes_long(payload->tempfile_name, remote_time);
	}

	if(ret == 0) {
		const char *realname = payload->tempfile_name;
		if(payload->destfile_name) {
			realname = payload->destfile_name;
			if(rename(payload->tempfile_name, payload->destfile_name)) {
				_alpm_log(handle, ALPM_LOG_ERROR, _("could not rename %s to %s (%s)\n"),
						payload->tempfile_name, payload->destfile_name, strerror(errno));
				ret = -1;
			}
		}
		if(ret != -1 && final_file) {
			STRDUP(*final_file, strrchr(realname, '/') + 1,
					RET_ERR(handle, ALPM_ERR_MEMORY, -1));
		}
	}

	if((ret == -1 || dload_interrupted) && payload->unlink_on_fail &&
			payload->tempfile_name) {
		unlink(payload->tempfile_name);
	}

	/* restore the old signal handlers */
	unmask_signal(SIGINT, &orig_sig_int);
	unmask_signal(SIGPIPE, &orig_sig_pipe);
	/* if we were interrupted, trip the old handler */
	if(dload_interrupted) {
		raise(SIGINT);
	}

	return ret;
}
示例#3
0
/*
 * Password was OK, execute a shell.
 */
static void sushell(struct passwd *pwd)
{
	char shell[PATH_MAX];
	char home[PATH_MAX];
	char *p;
	char *su_shell;

	/*
	 * Set directory and shell.
	 */
	if (chdir(pwd->pw_dir) != 0) {
		warn(_("%s: change directory failed"), pwd->pw_dir);
		printf(_("Logging in with home = \"/\".\n"));

		if (chdir("/") != 0)
			warn(_("change directory to system root failed"));
	}

	if ((p = getenv("SUSHELL")) != NULL)
		su_shell = p;
	else if ((p = getenv("sushell")) != NULL)
		su_shell = p;
	else {
		if (pwd->pw_shell[0])
			su_shell = pwd->pw_shell;
		else
			su_shell = "/bin/sh";
	}
	if ((p = strrchr(su_shell, '/')) == NULL)
		p = su_shell;
	else
		p++;

	snprintf(shell, sizeof(shell), profile ? "-%s" : "%s", p);

	/*
	 * Set some important environment variables.
	 */
	if (getcwd(home, sizeof(home)) != NULL)
		setenv("HOME", home, 1);

	setenv("LOGNAME", "root", 1);
	setenv("USER", "root", 1);
	if (!profile)
		setenv("SHLVL","0",1);

	/*
	 * Try to execute a shell.
	 */
	setenv("SHELL", su_shell, 1);
	unmask_signal(SIGINT, &saved_sigint);
	unmask_signal(SIGTSTP, &saved_sigtstp);
	unmask_signal(SIGQUIT, &saved_sigquit);

#ifdef HAVE_LIBSELINUX
	if (is_selinux_enabled() > 0) {
		security_context_t scon=NULL;
		char *seuser=NULL;
		char *level=NULL;
		if (getseuserbyname("root", &seuser, &level) == 0) {
			if (get_default_context_with_level(seuser, level, 0, &scon) == 0) {
				if (setexeccon(scon) != 0)
					warnx(_("setexeccon failed"));
				freecon(scon);
			}
		}
		free(seuser);
		free(level);
	}
#endif
	execl(su_shell, shell, NULL);
	warn(_("%s: exec failed"), su_shell);

	setenv("SHELL", "/bin/sh", 1);
	execl("/bin/sh", profile ? "-sh" : "sh", NULL);
	warn(_("%s: exec failed"), "/bin/sh");
}