示例#1
0
int main(int argc, char *argv[])
{
	static struct option longopts[] = {
		{ "log", required_argument, NULL, 'l' },
		{ "config", required_argument, NULL, 'c' },
		{ "version", no_argument, NULL,	'v' },
		{ NULL,  0,  NULL, 0 }
	};

	struct brubeck_server _server;
	const char *config_file = "config.default.json";
	const char *log_file = NULL;
	int opt;

	while ((opt = getopt_long(argc, argv, ":l:c:v", longopts, NULL)) != -1) {
		switch (opt) {
		case 'l': log_file = optarg; break;
		case 'c': config_file = optarg; break;
		case 'v':
			puts("brubeck " GIT_SHA);
			return 0;

		default:
			printf("Usage: %s [--log LOG_FILE] [--config CONFIG_FILE] [--version]\n", argv[0]);
			return 1;
		}
	}

	initproctitle(argc, argv);
	gh_log_open(log_file);
	brubeck_server_init(&_server, config_file);
	return brubeck_server_run(&_server);
}
示例#2
0
int main (int argc, char *argv[])
{
	syslog_open("nntpswitchd", LOG_PID, LOG_NEWS);

	init_options(argc, argv);

	init_sighandlers();
	initproctitle(argc, argv);

	if ((master = memmap(sizeof (MASTER))) == NULL)
		die("Can't allocate master memory");

	info("Server starting up..");

	run_daemon();

	syslog_close();
	
	return 0;
}
示例#3
0
int main(int argc, char **argv) {
    config_init(argc, argv);
    initproctitle(argc, argv);

    return _main(&CONFIG);
}
示例#4
0
int main(int argc, char *argv[]) {
	int efd, retval, prio;
	uint64_t u;
	ssize_t s;
	uid_t uid;
	fd_set set;
	char *memcg_path;
	struct timeval timeout;
	#ifndef NO_GPL
	char *pathcopy, *progname, cmdline[1024], *tty;
	int istty = 1;
	pid_t pgid;
	#endif

	/* maybe save a tiny number of bytes, because we can */
	mallopt(M_MXFAST, 0);

	if(argc > 2) {
		usage(argv[0]);
		exit(1);
	} else if(argc > 1 && argv[1][0] == '-') {
		/* any attempt at -helpme, etc */
		usage(argv[0]);
		return 1;
	}
	

	uid = getuid();
	/* don't monitor root */
	if(uid == 0)
		return 0;

	/* used for cmdline when this is not a tty */
	pgid = getpgrp();

	daemonize();

	/* be nice */
	prio = getpriority(PRIO_PROCESS, getpid());
	if(prio < TARGET_NICE)
		setpriority(PRIO_PROCESS, getpid(), TARGET_NICE);

	if(argc == 2)
		memcg_path = strdup(argv[1]);
	else
		memcg_path = get_cgroup_path();

	/* set cmdline for ps, top, etc. if you're not concerned about GPL */
	#ifndef NO_GPL
	pathcopy = strdup(argv[0]);
	progname = basename(pathcopy);
	initproctitle(argc, argv);
	tty = getenv("SSH_TTY");
	if(tty == NULL) {
		istty = 0;
		tty = malloc(256);
		snprintf(tty, 256, "[notty: pgid=%d]", pgid);
	}
	snprintf(cmdline, 1024, "%s %s", tty, memcg_path);
	setproctitle(progname, cmdline);
	if(!istty)
		free(tty);
	free(pathcopy);
	#endif


	efd = open_event_fd(memcg_path);

	free(memcg_path);

	while(1) {
		/* Check periodically if the user has other processes.
		   Exit if none exist */
		timeout.tv_sec = TIMEOUT_SECONDS;
		timeout.tv_usec = 0;
		FD_ZERO(&set);
		FD_SET(efd, &set);

		/* check for data in efd (i.e. oom triggered) */
		retval = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
		if(retval == -1) {
			handle_error("select returned -1");
		} else if(retval == 0) {
			if(!pipe_alive())
				return 0;
		} else {
			/* select() found data */
			s = read(efd, &u, sizeof(uint64_t));
			if (s != sizeof(uint64_t)) 
				handle_error("reading from event fd");

			/* Wait a moment for the oom-killer to take effect. */
			sleep(4);
			writeToTTY();
		}
	}
	return 2;
}
示例#5
0
int main(int argc, char *argv[])
{
    bool  recalculate = FALSE;
    int   len;
    err_t e;
    err_t err = NULL;
    char *infile;
    char *conn_name;
    int  lineno=0;
    struct connection *c1 = NULL;
    struct id moon, cassidy;
    struct adns_continuation *cr1 = NULL;

#ifdef HAVE_EFENCE
    EF_PROTECT_FREE=1;
#endif

    initproctitle(argc, argv);
    progname = argv[0];
    leak_detective = 1;

    if(argc != 3 && argc!=4) {
	fprintf(stderr, "Usage: %s [-r] <whackrecord> <conn-name>\n", progname);
	exit(10);
    }
    /* skip argv0 */
    argc--; argv++;

    if(strcmp(argv[0], "-r")==0) {
        recalculate = 1;    /* do all crypto */
        argc--; argv++;
    }

    tool_init_log();
    cur_debugging |= DBG_DNS;
    init_adns();

    {
    	int r;
	struct sigaction act;

	act.sa_handler = &childhandler;
	act.sa_flags   = SA_RESTART;
	r = sigaction(SIGCHLD, &act, NULL);
	passert(r == 0);
    }

    reset_globals();

    /* setup a query */
    cr1 = alloc_thing(struct adns_continuation, "moon lookup");
    moon.kind = ID_FQDN;
    strtochunk(moon.name, "moon.testing.openswan.org", "dns name");
    e = start_adns_query(&moon, NULL, ns_t_key,
                         moon_continue, cr1);
    freeanychunk(moon.name);
    process_dns_results();

#if 0
    cr1 = alloc_thing(struct adns_continuation, "cassidy lookup");
    cassidy.kind = ID_FQDN;
    strtochunk(cassidy.name, "cassidy.sandelman.ca", "dns name 2");
    e = start_adns_query(&cassidy, NULL, ns_t_key,
                         cassidy_continue, cr1);
    freeanychunk(cassidy.name);
    process_dns_results();
#endif

    /* re-use cassidy */
    cr1 = alloc_thing(struct adns_continuation, "cassidy A lookup");
    e = start_adns_hostname(AF_UNSPEC, "cassidy.sandelman.ca", cassidy_host_continue, cr1);
    process_dns_results();

    stop_adns();
    report_leaks();

    tool_close_log();
    exit(0);
}
示例#6
0
int main(int argc, char *argv[])
{
    err_t err = NULL;
    struct addrinfo hints, *result1, *result2;
    unsigned char buffer1[1024];
    unsigned int  buffer1_len = sizeof(buffer1);
    unsigned int  serial_size;
    int i,s;

#ifdef HAVE_EFENCE
    EF_PROTECT_FREE=1;
#endif

    initproctitle(argc, argv);
    progname = argv[0];
    leak_detective = 1;

    tool_init_log();
    cur_debugging |= DBG_DNS;

    zero(&hints);
    hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
    hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
    hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
    hints.ai_protocol = 0;          /* Any protocol */
    hints.ai_canonname = NULL;
    hints.ai_addr = NULL;
    hints.ai_next = NULL;

    if(argc==1) {
        printf("usage: %s [name]...\n", progname);
        exit(10);
    }

    for(i=1; i < argc; i++) {
        DBG_log("looking up: %s\n", argv[i]);
        s = getaddrinfo(argv[i], NULL, &hints, &result1);
        if(s!=0) {
            printf("lookup: %s a/aaaa lookup error: %s\n"
                             , argv[i], gai_strerror(s));
            continue;
        }
        /* sort things so they come out consistently */
        result1 = sort_addr_info(result1);
        dump_addr_info(result1);

        /* now serialize it into the buffer */
        serial_size = serialize_addr_info(result1, buffer1, buffer1_len);
        freeaddrinfo(result1);

        DBG_log("serialized size=%u\n", serial_size);
        result2 = deserialize_addr_info(buffer1, serial_size);
        dump_addr_info(result2);

        osw_freeaddrinfo(result2);
    }

    report_leaks();

    tool_close_log();
    exit(0);
}
示例#7
0
文件: rpmqv.c 项目: avokhmin/RPM5
int main(int argc, const char ** argv)
#endif
	/*@globals rpmEVR, RPMVERSION,
		rpmGlobalMacroContext, rpmCLIMacroContext,
		h_errno, fileSystem, internalState@*/
	/*@modifies fileSystem, internalState@*/
{
    poptContext optCon = rpmcliInit(argc, (char *const *)argv, optionsTable);

    rpmts ts = NULL;
    enum modes bigMode = MODE_UNKNOWN;

#if defined(IAM_RPMQV)
    QVA_t qva = &rpmQVKArgs;
#endif

#ifdef	IAM_RPMBT
    BTA_t ba = &rpmBTArgs;
#endif

#ifdef	IAM_RPMEIU
    QVA_t ia = &rpmIArgs;
#endif

#if defined(IAM_RPMDB)
    QVA_t da = &rpmDBArgs;
#endif

#if defined(IAM_RPMK)
    QVA_t ka = &rpmQVKArgs;
#endif

#if defined(IAM_RPMBT) || defined(IAM_RPMK)
    char * passPhrase = "";
#endif

    pid_t pipeChild = 0;
    int ec = 0;
    int status;
    int p[2];
#ifdef	IAM_RPMEIU
    int xx;
#endif
	
#if !defined(__GLIBC__) && !defined(__LCLINT__)
    environ = envp;
#else
/* XXX limit the fiddle up to linux for now. */
#if !defined(HAVE_SETPROCTITLE) && defined(__linux__)
    (void) initproctitle(argc, (char **)argv, environ);
#endif
#endif  

    /* Set the major mode based on argv[0] */
    /*@-nullpass@*/
#ifdef	IAM_RPMBT
    if (!strcmp(__progname, "rpmb"))	bigMode = MODE_BUILD;
    if (!strcmp(__progname, "lt-rpmb"))	bigMode = MODE_BUILD;
    if (!strcmp(__progname, "rpmt"))	bigMode = MODE_TARBUILD;
    if (!strcmp(__progname, "rpmbuild"))	bigMode = MODE_BUILD;
#endif
#ifdef	IAM_RPMQV
    if (!strcmp(__progname, "rpmq"))	bigMode = MODE_QUERY;
    if (!strcmp(__progname, "lt-rpmq"))	bigMode = MODE_QUERY;
    if (!strcmp(__progname, "rpmv"))	bigMode = MODE_VERIFY;
    if (!strcmp(__progname, "rpmquery"))	bigMode = MODE_QUERY;
    if (!strcmp(__progname, "rpmverify"))	bigMode = MODE_VERIFY;
#endif
#ifdef	RPMEIU
    if (!strcmp(__progname, "rpme"))	bigMode = MODE_ERASE;
    if (!strcmp(__progname, "rpmi"))	bigMode = MODE_INSTALL;
    if (!strcmp(__progname, "lt-rpmi"))	bigMode = MODE_INSTALL;
    if (!strcmp(__progname, "rpmu"))	bigMode = MODE_INSTALL;
#endif
    /*@=nullpass@*/

#if defined(IAM_RPMQV)
    /* Jumpstart option from argv[0] if necessary. */
    switch (bigMode) {
    case MODE_QUERY:	qva->qva_mode = 'q';	break;
    case MODE_VERIFY:	qva->qva_mode = 'V';	break;
    case MODE_CHECKSIG:	qva->qva_mode = 'K';	break;
    case MODE_RESIGN:	qva->qva_mode = 'R';	break;
    case MODE_INSTALL:
    case MODE_ERASE:
    case MODE_BUILD:
    case MODE_REBUILD:
    case MODE_RECOMPILE:
    case MODE_TARBUILD:
    case MODE_REBUILDDB:
    case MODE_UNKNOWN:
    default:
	break;
    }
#endif

    rpmcliConfigured();

#ifdef	IAM_RPMBT
    switch (ba->buildMode) {
    case 'b':	bigMode = MODE_BUILD;		break;
    case 't':	bigMode = MODE_TARBUILD;	break;
    case 'B':	bigMode = MODE_REBUILD;		break;
    case 'C':	bigMode = MODE_RECOMPILE;	break;
    }

    if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN)
	bigMode = MODE_BUILD;

    if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN)
	bigMode = MODE_BUILD;
#endif	/* IAM_RPMBT */
    
#ifdef	IAM_RPMDB
  if (bigMode == MODE_UNKNOWN || (bigMode & MODES_DB)) {
    if (da->rebuild) {
	if (bigMode != MODE_UNKNOWN) 
	    argerror(_("only one major mode may be specified"));
	else
	    bigMode = MODE_REBUILDDB;
    }
  }
#endif	/* IAM_RPMDB */

#ifdef	IAM_RPMQV
  if (bigMode == MODE_UNKNOWN || (bigMode & MODES_QV)) {
    switch (qva->qva_mode) {
    case 'q':	bigMode = MODE_QUERY;		break;
    case 'V':	bigMode = MODE_VERIFY;		break;
    }

    if (qva->qva_sourceCount) {
	if (qva->qva_sourceCount > 2)
	    argerror(_("one type of query/verify may be performed at a "
			"time"));
    }
    if (qva->qva_flags && (bigMode & ~MODES_QV)) 
	argerror(_("unexpected query flags"));

    if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
	argerror(_("unexpected query format"));

    if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
	argerror(_("unexpected query source"));
  }
#endif	/* IAM_RPMQV */

#ifdef	IAM_RPMEIU
  if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
    {	int iflags = (ia->installInterfaceFlags &
		(INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
	int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);

	if (iflags & eflags)
	    argerror(_("only one major mode may be specified"));
	else if (iflags)
	    bigMode = MODE_INSTALL;
	else if (eflags)
	    bigMode = MODE_ERASE;
    }
#endif	/* IAM_RPMEIU */

#ifdef	IAM_RPMK
  if (bigMode == MODE_UNKNOWN || (bigMode & MODES_K)) {
	switch (ka->qva_mode) {
	case RPMSIGN_NONE:
	    ka->sign = 0;
	    break;
	case RPMSIGN_IMPORT_PUBKEY:
	case RPMSIGN_CHK_SIGNATURE:
	    bigMode = MODE_CHECKSIG;
	    ka->sign = 0;
	    break;
	case RPMSIGN_ADD_SIGNATURE:
	case RPMSIGN_NEW_SIGNATURE:
	case RPMSIGN_DEL_SIGNATURE:
	    bigMode = MODE_RESIGN;
	    ka->sign = (ka->qva_mode != RPMSIGN_DEL_SIGNATURE);
	    break;
	}
  }
#endif	/* IAM_RPMK */

#if defined(IAM_RPMEIU)
    if (!( bigMode == MODE_INSTALL ) &&
(ia->probFilter & (RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_OLDPACKAGE)))
	argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
    if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_FORCERELOCATE))
	argerror(_("files may only be relocated during package installation"));

    if (ia->relocations && ia->qva_prefix)
	argerror(_("cannot use --prefix with --relocate or --excludepath"));

    if (bigMode != MODE_INSTALL && ia->relocations)
	argerror(_("--relocate and --excludepath may only be used when installing new packages"));

    if (bigMode != MODE_INSTALL && ia->qva_prefix)
	argerror(_("--prefix may only be used when installing new packages"));

    if (ia->qva_prefix && ia->qva_prefix[0] != '/') 
	argerror(_("arguments to --prefix must begin with a /"));

    if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_HASH))
	argerror(_("--hash (-h) may only be specified during package "
			"installation"));

    if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_PERCENT))
	argerror(_("--percent may only be specified during package "
			"installation"));

    if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_REPLACEPKG))
	argerror(_("--replacepkgs may only be specified during package "
			"installation"));

    if (bigMode != MODE_INSTALL && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
	argerror(_("--excludedocs may only be specified during package "
		   "installation"));

    if (bigMode != MODE_INSTALL && ia->incldocs)
	argerror(_("--includedocs may only be specified during package "
		   "installation"));

    if (ia->incldocs && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
	argerror(_("only one of --excludedocs and --includedocs may be "
		 "specified"));
  
    if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREARCH))
	argerror(_("--ignorearch may only be specified during package "
		   "installation"));

    if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREOS))
	argerror(_("--ignoreos may only be specified during package "
		   "installation"));

    if ((ia->installInterfaceFlags & INSTALL_ALLMATCHES) && bigMode != MODE_ERASE)
	argerror(_("--allmatches may only be specified during package "
		   "erasure"));

    if ((ia->transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
	argerror(_("--allfiles may only be specified during package "
		   "installation"));

    if ((ia->transFlags & RPMTRANS_FLAG_JUSTDB) &&
	bigMode != MODE_INSTALL && bigMode != MODE_ERASE)
	argerror(_("--justdb may only be specified during package "
		   "installation and erasure"));

    if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
	(ia->transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
	argerror(_("script disabling options may only be specified during "
		   "package installation and erasure"));

    if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
	(ia->transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
	argerror(_("trigger disabling options may only be specified during "
		   "package installation and erasure"));

    if (ia->noDeps & (bigMode & ~MODES_FOR_NODEPS))
	argerror(_("--nodeps may only be specified during package "
		   "building, rebuilding, recompilation, installation, "
		   "erasure, and verification"));

    if ((ia->transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
	argerror(_("--test may only be specified during package installation, "
		 "erasure, and building"));
#endif	/* IAM_RPMEIU */

    if (rpmioRootDir && rpmioRootDir[1] && (bigMode & ~MODES_FOR_ROOT))
	argerror(_("--root (-r) may only be specified during "
		 "installation, erasure, querying, and "
		 "database rebuilds"));

    if (rpmioRootDir) {
	switch (urlIsURL(rpmioRootDir)) {
	default:
	    if (bigMode & MODES_FOR_ROOT)
		break;
	    /*@fallthrough@*/
	case URL_IS_UNKNOWN:
	    if (rpmioRootDir[0] != '/')
		argerror(_("arguments to --root (-r) must begin with a /"));
	    break;
	}
    }

#if defined(RPM_VENDOR_OPENPKG) /* integrity-checking */
    integrity_check(__progname, bigMode);
#endif

#if defined(IAM_RPMBT) || defined(IAM_RPMK)
    if (0
#if defined(IAM_RPMBT)
    || ba->sign 
#endif
#if defined(IAM_RPMK)
    || ka->sign
#endif
    )
    /*@-branchstate@*/
    {
        if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD ||
	    bigMode == MODE_RESIGN || bigMode == MODE_TARBUILD)
	{
	    const char ** av;
	    struct stat sb;
	    int errors = 0;

	    if ((av = poptGetArgs(optCon)) == NULL) {
		fprintf(stderr, _("no files to sign\n"));
		errors++;
	    } else
	    while (*av) {
		if (Stat(*av, &sb)) {
		    fprintf(stderr, _("cannot access file %s\n"), *av);
		    errors++;
		}
		av++;
	    }

	    if (errors) {
		ec = errors;
		goto exit;
	    }

	
            if (poptPeekArg(optCon)
#if defined(IAM_RPMBT)
	    && !ba->nopassword 
#endif
#if defined(IAM_RPMK)
	    && !ka->nopassword
#endif
	    )
	    {
		passPhrase = Getpass(_("Enter pass phrase: "));
		if (rpmCheckPassPhrase(passPhrase)) {
		    fprintf(stderr, _("Pass phrase check failed\n"));
		    ec = EXIT_FAILURE;
		    goto exit;
		}
		fprintf(stderr, _("Pass phrase is good.\n"));
		/* XXX Getpass() should realloc instead. */
		passPhrase = xstrdup(passPhrase);
	    }
	}
    }
    /*@=branchstate@*/
#endif	/* IAM_RPMBT || IAM_RPMK */

    if (rpmioPipeOutput) {
	if (pipe(p) < 0) {
	    fprintf(stderr, _("creating a pipe for --pipe failed: %m\n"));
	    goto exit;
	}

	if (!(pipeChild = fork())) {
	    (void) close(p[1]);
	    (void) dup2(p[0], STDIN_FILENO);
	    (void) close(p[0]);
	    (void) execl("/bin/sh", "/bin/sh", "-c", rpmioPipeOutput, NULL);
	    fprintf(stderr, _("exec failed\n"));
	}

	(void) close(p[0]);
	(void) dup2(p[1], STDOUT_FILENO);
	(void) close(p[1]);
    }
	
    ts = rpmtsCreate();
    (void) rpmtsSetRootDir(ts, rpmioRootDir);
    switch (bigMode) {
#ifdef	IAM_RPMDB
    case MODE_REBUILDDB:
    {   rpmVSFlags vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
	rpmVSFlags ovsflags;
	if (rpmcliQueryFlags & VERIFY_DIGEST)
	    vsflags |= _RPMVSF_NODIGESTS;
	if (rpmcliQueryFlags & VERIFY_SIGNATURE)
	    vsflags |= _RPMVSF_NOSIGNATURES;
	ovsflags = rpmtsSetVSFlags(ts, vsflags);
	ec = rpmtsRebuildDB(ts);
	vsflags = rpmtsSetVSFlags(ts, ovsflags);
    }	break;
#endif	/* IAM_RPMDB */

#ifdef	IAM_RPMBT
    case MODE_REBUILD:
    case MODE_RECOMPILE:
    {	const char * pkg;
	int nbuilds = 0;

        while (!rpmIsVerbose())
	    rpmIncreaseVerbosity();

	if (!poptPeekArg(optCon))
	    argerror(_("no packages files given for rebuild"));

	ba->buildAmount =
	    RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL | RPMBUILD_CHECK;
	if (bigMode == MODE_REBUILD) {
	    ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
	    ba->buildAmount |= RPMBUILD_RMSOURCE;
	    ba->buildAmount |= RPMBUILD_RMSPEC;
	    ba->buildAmount |= RPMBUILD_CLEAN;
	    ba->buildAmount |= RPMBUILD_RMBUILD;
	}

	while ((pkg = poptGetArg(optCon))) {
	    if (nbuilds++ > 0) {
		rpmFreeMacros(NULL);
		rpmFreeRpmrc();
		(void) rpmReadConfigFiles(NULL, NULL);
	    }
	    ba->specFile = NULL;
	    ba->cookie = NULL;
	    ec = rpmInstallSource(ts, pkg, &ba->specFile, &ba->cookie);
	    if (ec == 0) {
		ba->rootdir = rpmioRootDir;
		ba->passPhrase = passPhrase;
		ec = build(ts, ba, NULL);
	    }
	    ba->cookie = _free(ba->cookie);
	    ba->specFile = _free(ba->specFile);

	    if (ec)
		/*@loopbreak@*/ break;
	}

    }	break;

    case MODE_BUILD:
    case MODE_TARBUILD:
    {	int nbuilds = 0;

#if defined(RPM_VENDOR_OPENPKG) /* no-auto-verbose-increase-for-track-and-fetch */
	if (ba->buildChar != 't' && ba->buildChar != 'f')
#endif
        while (!rpmIsVerbose())
	    rpmIncreaseVerbosity();
       
	switch (ba->buildChar) {
	case 'a':
	    ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
	    /*@fallthrough@*/
	case 'b':
	    ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
	    ba->buildAmount |= RPMBUILD_CLEAN;
#if defined(RPM_VENDOR_MANDRIVA)
	    if ((ba->buildChar == 'a' || ba->buildChar == 'b') && ba->shortCircuit)
#else
	    if ((ba->buildChar == 'b') && ba->shortCircuit)
#endif
		/*@innerbreak@*/ break;
	    /*@fallthrough@*/
	case 'i':
	    ba->buildAmount |= RPMBUILD_INSTALL;
	    ba->buildAmount |= RPMBUILD_CHECK;
	    if ((ba->buildChar == 'i') && ba->shortCircuit)
		/*@innerbreak@*/ break;
	    /*@fallthrough@*/
	case 'c':
	    ba->buildAmount |= RPMBUILD_BUILD;
	    if ((ba->buildChar == 'c') && ba->shortCircuit)
		/*@innerbreak@*/ break;
	    /*@fallthrough@*/
	case 'p':
	    ba->buildAmount |= RPMBUILD_PREP;
	    /*@innerbreak@*/ break;
	    
	case 'l':
	    ba->buildAmount |= RPMBUILD_FILECHECK;
	    /*@innerbreak@*/ break;
	case 's':
	    ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
#if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* no-deps-on-building-srpms */
	    /* enforce no dependency checking when rolling a source RPM */
	    ba->noDeps = 1;
#endif
	    /*@innerbreak@*/ break;
	case 't':	/* support extracting the "%track" script/section */
	    ba->buildAmount |= RPMBUILD_TRACK;
	    /* enforce no dependency checking and expansion of %setup, %patch and %prep macros */
	    ba->noDeps = 1;
	    rpmDefineMacro(NULL, "setup #", RMIL_CMDLINE);
	    rpmDefineMacro(NULL, "patch #", RMIL_CMDLINE);
	    rpmDefineMacro(NULL, "prep %%prep", RMIL_CMDLINE);
	    /*@innerbreak@*/ break;
	case 'f':
	    ba->buildAmount |= RPMBUILD_FETCHSOURCE;
	    ba->noDeps = 1;
	    /*@innerbreak@*/ break;
	}

	if (!poptPeekArg(optCon)) {
	    if (bigMode == MODE_BUILD)
		argerror(_("no spec files given for build"));
	    else
		argerror(_("no tar files given for build"));
	}

	while ((ba->specFile = poptGetArg(optCon))) {
	    if (nbuilds++ > 0) {
		rpmFreeMacros(NULL);
		rpmFreeRpmrc();
		(void) rpmReadConfigFiles(NULL, NULL);
	    }
	    ba->rootdir = rpmioRootDir;
	    ba->passPhrase = passPhrase;
	    ba->cookie = NULL;
	    ec = build(ts, ba, NULL);
	    if (ec)
		/*@loopbreak@*/ break;
	}
    }	break;
#endif	/* IAM_RPMBT */

#ifdef	IAM_RPMEIU
    case MODE_ERASE:
	ia->depFlags = global_depFlags;
	if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;

	if (!poptPeekArg(optCon)) {
	    if (ia->rbtid == 0)
		argerror(_("no packages given for erase"));
ia->transFlags |= RPMTRANS_FLAG_NOFDIGESTS;
ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
ia->rbCheck = rpmcliInstallCheck;
ia->rbOrder = rpmcliInstallOrder;
ia->rbRun = rpmcliInstallRun;
	    ec += rpmRollback(ts, ia, NULL);
	} else {
	    ec += rpmErase(ts, ia, (const char **) poptGetArgs(optCon));
	}
	break;

    case MODE_INSTALL:

	/* RPMTRANS_FLAG_KEEPOBSOLETE */

	ia->depFlags = global_depFlags;
	if (!ia->incldocs) {
	    if (ia->transFlags & RPMTRANS_FLAG_NODOCS) {
		;
	    } else if (rpmExpandNumeric("%{_excludedocs}"))
		ia->transFlags |= RPMTRANS_FLAG_NODOCS;
	}

	if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;

	/* we've already ensured !(!ia->prefix && !ia->relocations) */
	/*@-branchstate@*/
	if (ia->qva_prefix) {
	    xx = rpmfiAddRelocation(&ia->relocations, &ia->nrelocations,
			NULL, ia->qva_prefix);
	    xx = rpmfiAddRelocation(&ia->relocations, &ia->nrelocations,
			NULL, NULL);
	} else if (ia->relocations) {
	    xx = rpmfiAddRelocation(&ia->relocations, &ia->nrelocations,
			NULL, NULL);
	}
	/*@=branchstate@*/

	if (!poptPeekArg(optCon)) {
	    if (ia->rbtid == 0)
		argerror(_("no packages given for install"));
ia->transFlags |= RPMTRANS_FLAG_NOFDIGESTS;
ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
ia->rbCheck = rpmcliInstallCheck;
ia->rbOrder = rpmcliInstallOrder;
ia->rbRun = rpmcliInstallRun;
/*@i@*/	    ec += rpmRollback(ts, ia, NULL);
	} else {
	    /*@-compdef -compmempass@*/ /* FIX: ia->relocations[0].newPath undefined */
	    ec += rpmcliInstall(ts, ia, (const char **)poptGetArgs(optCon));
	    /*@=compdef =compmempass@*/
	}
	break;

#endif	/* IAM_RPMEIU */

#ifdef	IAM_RPMQV
    case MODE_QUERY:
	if (!poptPeekArg(optCon)
	 && !(qva->qva_source == RPMQV_ALL || qva->qva_source == RPMQV_HDLIST))
	    argerror(_("no arguments given for query"));

	qva->depFlags = global_depFlags;
	qva->qva_specQuery = rpmspecQuery;
	ec = rpmcliQuery(ts, qva, (const char **) poptGetArgs(optCon));
	qva->qva_specQuery = NULL;
	break;

    case MODE_VERIFY:
    {	rpmVerifyFlags verifyFlags = VERIFY_ALL;

	qva->depFlags = global_depFlags;
	verifyFlags &= ~qva->qva_flags;
	qva->qva_flags = (rpmQueryFlags) verifyFlags;

	if (!poptPeekArg(optCon)
	 && !(qva->qva_source == RPMQV_ALL || qva->qva_source == RPMQV_HDLIST))
	    argerror(_("no arguments given for verify"));
	ec = rpmcliVerify(ts, qva, (const char **) poptGetArgs(optCon));
    }	break;
#endif	/* IAM_RPMQV */

#ifdef IAM_RPMK
    case MODE_CHECKSIG:
    {	rpmVerifyFlags verifyFlags =
		(VERIFY_FDIGEST|VERIFY_HDRCHK|VERIFY_DIGEST|VERIFY_SIGNATURE);

	verifyFlags &= ~ka->qva_flags;
	ka->qva_flags = (rpmQueryFlags) verifyFlags;
    }   /*@fallthrough@*/
    case MODE_RESIGN:
	if (!poptPeekArg(optCon))
	    argerror(_("no arguments given"));
	ka->passPhrase = passPhrase;
	ec = rpmcliSign(ts, ka, (const char **)poptGetArgs(optCon));
    	break;
#endif	/* IAM_RPMK */
	
#if !defined(IAM_RPMQV)
    case MODE_QUERY:
    case MODE_VERIFY:
#endif
#if !defined(IAM_RPMK)
    case MODE_CHECKSIG:
    case MODE_RESIGN:
#endif
#if !defined(IAM_RPMDB)
    case MODE_REBUILDDB:
#endif
#if !defined(IAM_RPMBT)
    case MODE_BUILD:
    case MODE_REBUILD:
    case MODE_RECOMPILE:
    case MODE_TARBUILD:
#endif
#if !defined(IAM_RPMEIU)
    case MODE_INSTALL:
    case MODE_ERASE:
#endif
    case MODE_UNKNOWN:
#ifdef	DYING /* XXX rpmIsVerbose alone stops usage spewage with every --eval */
	if (poptPeekArg(optCon) != NULL || argc <= 1 || rpmIsVerbose()) {
	    printUsage(optCon, stderr, 0);
	    ec = argc;
	}
#endif
	break;
    }

#if defined(IAM_RPMBT) || defined(IAM_RPMK)
exit:
#endif	/* IAM_RPMBT || IAM_RPMK */

    (void)rpmtsFree(ts); 
    ts = NULL;

    if (pipeChild) {
	(void) fclose(stdout);
	(void) waitpid(pipeChild, &status, 0);
    }

#ifdef	IAM_RPMQV
    qva->qva_queryFormat = _free(qva->qva_queryFormat);
#endif

#ifdef	IAM_RPMBT
    freeNames();
    /* XXX _specPool/_pkgPool teardown should be done somewhere else. */
    {	extern rpmioPool _pkgPool;
	extern rpmioPool _specPool;
	_pkgPool = rpmioFreePool(_pkgPool);
	_specPool = rpmioFreePool(_specPool);
    }
#endif

#ifdef	IAM_RPMEIU
    ia->relocations = rpmfiFreeRelocations(ia->relocations);
#endif

    optCon = rpmcliFini(optCon);

/* XXX limit the fiddle up to linux for now. */
#if !defined(HAVE_SETPROCTITLE) && defined(__linux__)
    (void) finiproctitle();
#endif

    /* XXX don't overflow single byte exit status */
    /* XXX status 255 is special to xargs(1) */
    if (ec > 254) ec = 254;

     rpmlog(RPMLOG_DEBUG, D_("exit code: %d\n"), ec);

    /*@-globstate@*/
    return ec;
    /*@=globstate@*/
}
示例#8
0
int
main(int argc, char **argv)
{
    extern int optind;
    extern char *optarg, **environ;
    struct group *gr;
    register int ch;
    register char *p;
    int ask, fflag, hflag, pflag, cnt, errsv;
    int quietlog, passwd_req;
    char *domain, *ttyn;
    char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
    char *termenv;
    char *childArgv[10];
    char *buff;
    int childArgc = 0;
#ifdef HAVE_SECURITY_PAM_MISC_H
    int retcode;
    pam_handle_t *pamh = NULL;
    struct pam_conv conv = { misc_conv, NULL };
    pid_t childPid;
#else
    char *salt, *pp;
#endif
#ifdef LOGIN_CHOWN_VCS
    char vcsn[20], vcsan[20];
#endif

    pid = getpid();

    signal(SIGALRM, timedout);
    alarm((unsigned int)timeout);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGINT, SIG_IGN);

    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
    
    setpriority(PRIO_PROCESS, 0, 0);
    initproctitle(argc, argv);
    
    /*
     * -p is used by getty to tell login not to destroy the environment
     * -f is used to skip a second login authentication 
     * -h is used by other servers to pass the name of the remote
     *    host to login so that it may be placed in utmp and wtmp
     */
    gethostname(tbuf, sizeof(tbuf));
    xstrncpy(thishost, tbuf, sizeof(thishost));
    domain = index(tbuf, '.');
    
    username = tty_name = hostname = NULL;
    fflag = hflag = pflag = 0;
    passwd_req = 1;

    while ((ch = getopt(argc, argv, "fh:p")) != -1)
      switch (ch) {
	case 'f':
	  fflag = 1;
	  break;
	  
	case 'h':
	  if (getuid()) {
	      fprintf(stderr,
		      _("login: -h for super-user only.\n"));
	      exit(1);
	  }
	  hflag = 1;
	  if (domain && (p = index(optarg, '.')) &&
	      strcasecmp(p, domain) == 0)
	    *p = 0;

	  hostname = strdup(optarg); 	/* strdup: Ambrose C. Li */
	  {
		  struct hostent *he = gethostbyname(hostname);

		  /* he points to static storage; copy the part we use */
		  hostaddress[0] = 0;
		  if (he && he->h_addr_list && he->h_addr_list[0])
			  memcpy(hostaddress, he->h_addr_list[0],
				 sizeof(hostaddress));
	  }
	  break;
	  
	case 'p':
	  pflag = 1;
	  break;

	case '?':
	default:
	  fprintf(stderr,
		  _("usage: login [-fp] [username]\n"));
	  exit(1);
      }
    argc -= optind;
    argv += optind;
    if (*argv) {
	char *p = *argv;
	username = strdup(p);
	ask = 0;
	/* wipe name - some people mistype their password here */
	/* (of course we are too late, but perhaps this helps a little ..) */
	while(*p)
	    *p++ = ' ';
    } else
        ask = 1;

    for (cnt = getdtablesize(); cnt > 2; cnt--)
      close(cnt);
    
    ttyn = ttyname(0);

    if (ttyn == NULL || *ttyn == '\0') {
	/* no snprintf required - see definition of tname */
	sprintf(tname, "%s??", _PATH_TTY);
	ttyn = tname;
    }

    check_ttyname(ttyn);

    if (strncmp(ttyn, "/dev/", 5) == 0)
	tty_name = ttyn+5;
    else
	tty_name = ttyn;

    if (strncmp(ttyn, "/dev/tty", 8) == 0)
	tty_number = ttyn+8;
    else {
	char *p = ttyn;
	while (*p && !isdigit(*p)) p++;
	tty_number = p;
    }

#ifdef LOGIN_CHOWN_VCS
    /* find names of Virtual Console devices, for later mode change */
    snprintf(vcsn, sizeof(vcsn), "/dev/vcs%s", tty_number);
    snprintf(vcsan, sizeof(vcsan), "/dev/vcsa%s", tty_number);
#endif

    /* set pgid to pid */
    setpgrp();
    /* this means that setsid() will fail */
    
    {
	struct termios tt, ttt;
	
	tcgetattr(0, &tt);
	ttt = tt;
	ttt.c_cflag &= ~HUPCL;

	/* These can fail, e.g. with ttyn on a read-only filesystem */
	chown(ttyn, 0, 0);
	chmod(ttyn, TTY_MODE);

	/* Kill processes left on this tty */
	tcsetattr(0,TCSAFLUSH,&ttt);
	signal(SIGHUP, SIG_IGN); /* so vhangup() wont kill us */
	vhangup();
	signal(SIGHUP, SIG_DFL);

	/* open stdin,stdout,stderr to the tty */
	opentty(ttyn);
	
	/* restore tty modes */
	tcsetattr(0,TCSAFLUSH,&tt);
    }

    openlog("login", LOG_ODELAY, LOG_AUTHPRIV);

#if 0
    /* other than iso-8859-1 */
    printf("\033(K");
    fprintf(stderr,"\033(K");
#endif

#ifdef HAVE_SECURITY_PAM_MISC_H
    /*
     * username is initialized to NULL
     * and if specified on the command line it is set.
     * Therefore, we are safe not setting it to anything
     */

    retcode = pam_start("login",username, &conv, &pamh);
    if(retcode != PAM_SUCCESS) {
	fprintf(stderr, _("login: PAM Failure, aborting: %s\n"),
		pam_strerror(pamh, retcode));
	syslog(LOG_ERR, _("Couldn't initialize PAM: %s"),
	       pam_strerror(pamh, retcode));
	exit(99);
    }
    /* hostname & tty are either set to NULL or their correct values,
       depending on how much we know */
    retcode = pam_set_item(pamh, PAM_RHOST, hostname);
    PAM_FAIL_CHECK;
    retcode = pam_set_item(pamh, PAM_TTY, tty_name);
    PAM_FAIL_CHECK;

    /*
     * [email protected]: Provide a user prompt to PAM
     * so that the "login: "******"Password: "******"login: "******"\033(K");
    fprintf(stderr,"\033(K");
#endif
	    
    /* if fflag == 1, then the user has already been authenticated */
    if (fflag && (getuid() == 0))
	passwd_req = 0;
    else
	passwd_req = 1;

    if(passwd_req == 1) {
	int failcount=0;

	/* if we didn't get a user on the command line, set it to NULL */
	pam_get_item(pamh,  PAM_USER, (const void **) &username);
	if (!username)
		pam_set_item(pamh, PAM_USER, NULL);

	/* there may be better ways to deal with some of these
	   conditions, but at least this way I don't think we'll
	   be giving away information... */
	/* Perhaps someday we can trust that all PAM modules will
	   pay attention to failure count and get rid of MAX_LOGIN_TRIES? */

	retcode = pam_authenticate(pamh, 0);
	while((failcount++ < PAM_MAX_LOGIN_TRIES) &&
	      ((retcode == PAM_AUTH_ERR) ||
	       (retcode == PAM_USER_UNKNOWN) ||
	       (retcode == PAM_CRED_INSUFFICIENT) ||
	       (retcode == PAM_AUTHINFO_UNAVAIL))) {
	    pam_get_item(pamh, PAM_USER, (const void **) &username);

	    syslog(LOG_NOTICE,_("FAILED LOGIN %d FROM %s FOR %s, %s"),
		   failcount, hostname, username, pam_strerror(pamh, retcode));
	    logbtmp(tty_name, username, hostname);

	    fprintf(stderr,_("Login incorrect\n\n"));
	    pam_set_item(pamh,PAM_USER,NULL);
	    retcode = pam_authenticate(pamh, 0);
	}

	if (retcode != PAM_SUCCESS) {
	    pam_get_item(pamh, PAM_USER, (const void **) &username);

	    if (retcode == PAM_MAXTRIES)
		syslog(LOG_NOTICE,_("TOO MANY LOGIN TRIES (%d) FROM %s FOR "
			"%s, %s"), failcount, hostname, username,
			 pam_strerror(pamh, retcode));
	    else
		syslog(LOG_NOTICE,_("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
			hostname, username, pam_strerror(pamh, retcode));
	    logbtmp(tty_name, username, hostname);

	    fprintf(stderr,_("\nLogin incorrect\n"));
	    pam_end(pamh, retcode);
	    exit(0);
	}

	retcode = pam_acct_mgmt(pamh, 0);

	if(retcode == PAM_NEW_AUTHTOK_REQD) {
	    retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
	}

	PAM_FAIL_CHECK;
    }

    /*
     * Grab the user information out of the password file for future usage
     * First get the username that we are actually using, though.
     */
    retcode = pam_get_item(pamh, PAM_USER, (const void **) &username);
    PAM_FAIL_CHECK;

    if (!username || !*username) {
	    fprintf(stderr, _("\nSession setup problem, abort.\n"));
	    syslog(LOG_ERR, _("NULL user name in %s:%d. Abort."),
		   __FUNCTION__, __LINE__);
	    pam_end(pamh, PAM_SYSTEM_ERR);
	    exit(1);
    }
    if (!(pwd = getpwnam(username))) {
	    fprintf(stderr, _("\nSession setup problem, abort.\n"));
	    syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
		   username, __FUNCTION__, __LINE__);
	    pam_end(pamh, PAM_SYSTEM_ERR);
	    exit(1);
    }

    /*
     * Create a copy of the pwd struct - otherwise it may get
     * clobbered by PAM
     */
    memcpy(&pwdcopy, pwd, sizeof(*pwd));
    pwd = &pwdcopy;
    pwd->pw_name   = strdup(pwd->pw_name);
    pwd->pw_passwd = strdup(pwd->pw_passwd);
    pwd->pw_gecos  = strdup(pwd->pw_gecos);
    pwd->pw_dir    = strdup(pwd->pw_dir);
    pwd->pw_shell  = strdup(pwd->pw_shell);
    if (!pwd->pw_name || !pwd->pw_passwd || !pwd->pw_gecos ||
	!pwd->pw_dir || !pwd->pw_shell) {
	    fprintf(stderr, _("login: Out of memory\n"));
	    syslog(LOG_ERR, "Out of memory");
	    pam_end(pamh, PAM_SYSTEM_ERR);
	    exit(1);
    }
    username = pwd->pw_name;

    /*
     * Initialize the supplementary group list.
     * This should be done before pam_setcred because
     * the PAM modules might add groups during pam_setcred.
     */
    if (initgroups(username, pwd->pw_gid) < 0) {
	    syslog(LOG_ERR, "initgroups: %m");
	    fprintf(stderr, _("\nSession setup problem, abort.\n"));
	    pam_end(pamh, PAM_SYSTEM_ERR);
	    exit(1);
    }

    retcode = pam_open_session(pamh, 0);
    PAM_FAIL_CHECK;

    retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
    PAM_FAIL_CHECK;

#else /* ! HAVE_SECURITY_PAM_MISC_H */

    for (cnt = 0;; ask = 1) {

	if (ask) {
	    fflag = 0;
	    getloginname();
	}

	/* Dirty patch to fix a gigantic security hole when using 
	   yellow pages. This problem should be solved by the
	   libraries, and not by programs, but this must be fixed
	   urgently! If the first char of the username is '+', we 
	   avoid login success.
	   Feb 95 <*****@*****.**> */
	
	if (username[0] == '+') {
	    puts(_("Illegal username"));
	    badlogin(username);
	    sleepexit(1);
	}
	
	/* (void)strcpy(tbuf, username); why was this here? */
	if ((pwd = getpwnam(username))) {
#  ifdef SHADOW_PWD
	    struct spwd *sp;
	    
	    if ((sp = getspnam(username)))
	      pwd->pw_passwd = sp->sp_pwdp;
#  endif
	    salt = pwd->pw_passwd;
	} else
	  salt = "xx";
	
	if (pwd) {
	    initgroups(username, pwd->pw_gid);
	    checktty(username, tty_name, pwd); /* in checktty.c */
	}
	
	/* if user not super-user, check for disabled logins */
	if (pwd == NULL || pwd->pw_uid)
	  checknologin();
	
	/*
	 * Disallow automatic login to root; if not invoked by
	 * root, disallow if the uid's differ.
	 */
	if (fflag && pwd) {
	    int uid = getuid();
	    
	    passwd_req = pwd->pw_uid == 0 ||
	      (uid && uid != pwd->pw_uid);
	}
	
	/*
	 * If trying to log in as root, but with insecure terminal,
	 * refuse the login attempt.
	 */
	if (pwd && pwd->pw_uid == 0 && !rootterm(tty_name)) {
	    fprintf(stderr,
		    _("%s login refused on this terminal.\n"),
		    pwd->pw_name);
	    
	    if (hostname)
	      syslog(LOG_NOTICE,
		     _("LOGIN %s REFUSED FROM %s ON TTY %s"),
		     pwd->pw_name, hostname, tty_name);
	    else
	      syslog(LOG_NOTICE,
		     _("LOGIN %s REFUSED ON TTY %s"),
		     pwd->pw_name, tty_name);
	    continue;
	}

	/*
	 * If no pre-authentication and a password exists
	 * for this user, prompt for one and verify it.
	 */
	if (!passwd_req || (pwd && !*pwd->pw_passwd))
	  break;
	
	setpriority(PRIO_PROCESS, 0, -4);
	pp = getpass(_("Password: "******"CRYPTO", 6) == 0) {
	    if (pwd && cryptocard()) break;
	}
#  endif /* CRYPTOCARD */
	
	p = crypt(pp, salt);
	setpriority(PRIO_PROCESS, 0, 0);

#  ifdef KERBEROS
	/*
	 * If not present in pw file, act as we normally would.
	 * If we aren't Kerberos-authenticated, try the normal
	 * pw file for a password.  If that's ok, log the user
	 * in without issueing any tickets.
	 */
	
	if (pwd && !krb_get_lrealm(realm,1)) {
	    /*
	     * get TGT for local realm; be careful about uid's
	     * here for ticket file ownership
	     */
	    setreuid(geteuid(),pwd->pw_uid);
	    kerror = krb_get_pw_in_tkt(pwd->pw_name, "", realm,
				       "krbtgt", realm, DEFAULT_TKT_LIFE, pp);
	    setuid(0);
	    if (kerror == INTK_OK) {
		memset(pp, 0, strlen(pp));
		notickets = 0;	/* user got ticket */
		break;
	    }
	}
#  endif /* KERBEROS */
	memset(pp, 0, strlen(pp));

	if (pwd && !strcmp(p, pwd->pw_passwd))
	  break;
	
	printf(_("Login incorrect\n"));
	badlogin(username); /* log ALL bad logins */
	failures++;
	
	/* we allow 10 tries, but after 3 we start backing off */
	if (++cnt > 3) {
	    if (cnt >= 10) {
		sleepexit(1);
	    }
	    sleep((unsigned int)((cnt - 3) * 5));
	}
    }
#endif /* !HAVE_SECURITY_PAM_MISC_H */
    
    /* committed to login -- turn off timeout */
    alarm((unsigned int)0);
    
    endpwent();
    
    /* This requires some explanation: As root we may not be able to
       read the directory of the user if it is on an NFS mounted
       filesystem. We temporarily set our effective uid to the user-uid
       making sure that we keep root privs. in the real uid. 
       
       A portable solution would require a fork(), but we rely on Linux
       having the BSD setreuid() */
    
    {
	char tmpstr[MAXPATHLEN];
	uid_t ruid = getuid();
	gid_t egid = getegid();

	/* avoid snprintf - old systems do not have it, or worse,
	   have a libc in which snprintf is the same as sprintf */
	if (strlen(pwd->pw_dir) + sizeof(_PATH_HUSHLOGIN) + 2 > MAXPATHLEN)
		quietlog = 0;
	else {
		sprintf(tmpstr, "%s/%s", pwd->pw_dir, _PATH_HUSHLOGIN);
		setregid(-1, pwd->pw_gid);
		setreuid(0, pwd->pw_uid);
		quietlog = (access(tmpstr, R_OK) == 0);
		setuid(0); /* setreuid doesn't do it alone! */
		setreuid(ruid, 0);
		setregid(-1, egid);
	}
    }
    
    /* for linux, write entries in utmp and wtmp */
    {
	struct utmp ut;
	struct utmp *utp;
	
	utmpname(_PATH_UTMP);
	setutent();

	/* Find pid in utmp.
login sometimes overwrites the runlevel entry in /var/run/utmp,
confusing sysvinit. I added a test for the entry type, and the problem
was gone. (In a runlevel entry, st_pid is not really a pid but some number
calculated from the previous and current runlevel).
Michael Riepe <*****@*****.**>
	*/
	while ((utp = getutent()))
		if (utp->ut_pid == pid
		    && utp->ut_type >= INIT_PROCESS
		    && utp->ut_type <= DEAD_PROCESS)
			break;

	/* If we can't find a pre-existing entry by pid, try by line.
	   BSD network daemons may rely on this. (anonymous) */
	if (utp == NULL) {
	     setutent();
	     ut.ut_type = LOGIN_PROCESS;
	     strncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
	     utp = getutline(&ut);
	}
	
	if (utp) {
	    memcpy(&ut, utp, sizeof(ut));
	} else {
	    /* some gettys/telnetds don't initialize utmp... */
	    memset(&ut, 0, sizeof(ut));
	}
	
	if (ut.ut_id[0] == 0)
	  strncpy(ut.ut_id, tty_number, sizeof(ut.ut_id));
	
	strncpy(ut.ut_user, username, sizeof(ut.ut_user));
	xstrncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
#ifdef _HAVE_UT_TV		/* in <utmpbits.h> included by <utmp.h> */
	gettimeofday(&ut.ut_tv, NULL);
#else
	{
	    time_t t;
	    time(&t);
	    ut.ut_time = t;	/* ut_time is not always a time_t */
				/* glibc2 #defines it as ut_tv.tv_sec */
	}
#endif
	ut.ut_type = USER_PROCESS;
	ut.ut_pid = pid;
	if (hostname) {
		xstrncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
		if (hostaddress[0])
			memcpy(&ut.ut_addr, hostaddress, sizeof(ut.ut_addr));
	}
	
	pututline(&ut);
	endutent();

#if HAVE_UPDWTMP
	updwtmp(_PATH_WTMP, &ut);
#else
#if 0
	/* The O_APPEND open() flag should be enough to guarantee
	   atomic writes at end of file. */
	{
	    int wtmp;

	    if((wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
		write(wtmp, (char *)&ut, sizeof(ut));
		close(wtmp);
	    }
	}
#else
	/* Probably all this locking below is just nonsense,
	   and the short version is OK as well. */
	{ 
	    int lf, wtmp;
	    if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) {
		flock(lf, LOCK_EX);
		if ((wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
		    write(wtmp, (char *)&ut, sizeof(ut));
		    close(wtmp);
		}
		flock(lf, LOCK_UN);
		close(lf);
	    }
	}
#endif
#endif
    }
    
    dolastlog(quietlog);
    
    chown(ttyn, pwd->pw_uid,
	  (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
    chmod(ttyn, TTY_MODE);

#ifdef LOGIN_CHOWN_VCS
    /* if tty is one of the VC's then change owner and mode of the 
       special /dev/vcs devices as well */
    if (consoletty(0)) {
	chown(vcsn, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid));
	chown(vcsan, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid));
	chmod(vcsn, TTY_MODE);
	chmod(vcsan, TTY_MODE);
    }
#endif

    setgid(pwd->pw_gid);
    
    if (*pwd->pw_shell == '\0')
      pwd->pw_shell = _PATH_BSHELL;
    
    /* preserve TERM even without -p flag */
    {
	char *ep;
	
	if(!((ep = getenv("TERM")) && (termenv = strdup(ep))))
	  termenv = "dumb";
    }
    
    /* destroy environment unless user has requested preservation */
    if (!pflag)
      {
          environ = (char**)malloc(sizeof(char*));
	  memset(environ, 0, sizeof(char*));
      }
    
    setenv("HOME", pwd->pw_dir, 0);      /* legal to override */
    if(pwd->pw_uid)
      setenv("PATH", _PATH_DEFPATH, 1);
    else
      setenv("PATH", _PATH_DEFPATH_ROOT, 1);
    
    setenv("SHELL", pwd->pw_shell, 1);
    setenv("TERM", termenv, 1);
    
    /* mailx will give a funny error msg if you forget this one */
    {
      char tmp[MAXPATHLEN];
      /* avoid snprintf */
      if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < MAXPATHLEN) {
	      sprintf(tmp, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
	      setenv("MAIL",tmp,0);
      }
    }
    
    /* LOGNAME is not documented in login(1) but
       HP-UX 6.5 does it. We'll not allow modifying it.
       */
    setenv("LOGNAME", pwd->pw_name, 1);

#ifdef HAVE_SECURITY_PAM_MISC_H
    {
	int i;
	char ** env = pam_getenvlist(pamh);

	if (env != NULL) {
	    for (i=0; env[i]; i++) {
		putenv(env[i]);
		/* D(("env[%d] = %s", i,env[i])); */
	    }
	}
    }
#endif

    setproctitle("login", username);
    
    if (!strncmp(tty_name, "ttyS", 4))
      syslog(LOG_INFO, _("DIALUP AT %s BY %s"), tty_name, pwd->pw_name);
    
    /* allow tracking of good logins.
       -steve philp ([email protected]) */
    
    if (pwd->pw_uid == 0) {
	if (hostname)
	  syslog(LOG_NOTICE, _("ROOT LOGIN ON %s FROM %s"),
		 tty_name, hostname);
	else
	  syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), tty_name);
    } else {
	if (hostname) 
	  syslog(LOG_INFO, _("LOGIN ON %s BY %s FROM %s"), tty_name, 
		 pwd->pw_name, hostname);
	else 
	  syslog(LOG_INFO, _("LOGIN ON %s BY %s"), tty_name, 
		 pwd->pw_name);
    }
    
    if (!quietlog) {
	motd();

#ifdef LOGIN_STAT_MAIL
	/*
	 * This turns out to be a bad idea: when the mail spool
	 * is NFS mounted, and the NFS connection hangs, the
	 * login hangs, even root cannot login.
	 * Checking for mail should be done from the shell.
	 */
	{
	    struct stat st;
	    char *mail;
	
	    mail = getenv("MAIL");
	    if (mail && stat(mail, &st) == 0 && st.st_size != 0) {
		if (st.st_mtime > st.st_atime)
			printf(_("You have new mail.\n"));
		else
			printf(_("You have mail.\n"));
	    }
	}
#endif
    }
    
    signal(SIGALRM, SIG_DFL);
    signal(SIGQUIT, SIG_DFL);
    signal(SIGTSTP, SIG_IGN);

#ifdef HAVE_SECURITY_PAM_MISC_H
    /*
     * We must fork before setuid() because we need to call
     * pam_close_session() as root.
     */
    
    childPid = fork();
    if (childPid < 0) {
       int errsv = errno;
       /* error in fork() */
       fprintf(stderr, _("login: failure forking: %s"), strerror(errsv));
       PAM_END;
       exit(0);
    }

    if (childPid) {
       /* parent - wait for child to finish, then cleanup session */
       signal(SIGHUP, SIG_IGN);
       signal(SIGINT, SIG_IGN);
       signal(SIGQUIT, SIG_IGN);
       signal(SIGTSTP, SIG_IGN);
       signal(SIGTTIN, SIG_IGN);
       signal(SIGTTOU, SIG_IGN);

       wait(NULL);
       PAM_END;
       exit(0);
    }

    /* child */
    /*
     * Problem: if the user's shell is a shell like ash that doesnt do
     * setsid() or setpgrp(), then a ctrl-\, sending SIGQUIT to every
     * process in the pgrp, will kill us.
     */

    /* start new session */
    setsid();

    /* make sure we have a controlling tty */
    opentty(ttyn);
    openlog("login", LOG_ODELAY, LOG_AUTHPRIV);	/* reopen */

    /*
     * TIOCSCTTY: steal tty from other process group.
     */
    if (ioctl(0, TIOCSCTTY, 1))
	    syslog(LOG_ERR, _("TIOCSCTTY failed: %m"));
#endif
    signal(SIGINT, SIG_DFL);
    
    /* discard permissions last so can't get killed and drop core */
    if(setuid(pwd->pw_uid) < 0 && pwd->pw_uid) {
	syslog(LOG_ALERT, _("setuid() failed"));
	exit(1);
    }
    
    /* wait until here to change directory! */
    if (chdir(pwd->pw_dir) < 0) {
	printf(_("No directory %s!\n"), pwd->pw_dir);
	if (chdir("/"))
	  exit(0);
	pwd->pw_dir = "/";
	printf(_("Logging in with home = \"/\".\n"));
    }
    
    /* if the shell field has a space: treat it like a shell script */
    if (strchr(pwd->pw_shell, ' ')) {
	buff = malloc(strlen(pwd->pw_shell) + 6);

	if (!buff) {
	    fprintf(stderr, _("login: no memory for shell script.\n"));
	    exit(0);
	}

	strcpy(buff, "exec ");
	strcat(buff, pwd->pw_shell);
	childArgv[childArgc++] = "/bin/sh";
	childArgv[childArgc++] = "-sh";
	childArgv[childArgc++] = "-c";
	childArgv[childArgc++] = buff;
    } else {
	tbuf[0] = '-';
	xstrncpy(tbuf + 1, ((p = rindex(pwd->pw_shell, '/')) ?
			   p + 1 : pwd->pw_shell),
		sizeof(tbuf)-1);
	
	childArgv[childArgc++] = pwd->pw_shell;
	childArgv[childArgc++] = tbuf;
    }

    childArgv[childArgc++] = NULL;

    execvp(childArgv[0], childArgv + 1);

    errsv = errno;

    if (!strcmp(childArgv[0], "/bin/sh"))
	fprintf(stderr, _("login: couldn't exec shell script: %s.\n"),
		strerror(errsv));
    else
	fprintf(stderr, _("login: no shell: %s.\n"), strerror(errsv));

    exit(0);
}
示例#9
0
int main(int argc, char **argv)
{
	int c;
	int cnt;
	char *childArgv[10];
	char *buff;
	int childArgc = 0;
	int retcode;

	char *pwdbuf = NULL;
	struct passwd *pwd = NULL, _pwd;

	struct login_context cxt = {
		.tty_mode = TTY_MODE,		/* tty chmod() */
		.pid = getpid(),		/* PID */
		.conv = { misc_conv, NULL }	/* PAM conversation function */
	};

	timeout = getlogindefs_num("LOGIN_TIMEOUT", LOGIN_TIMEOUT);

	signal(SIGALRM, timedout);
	siginterrupt(SIGALRM, 1);	/* we have to interrupt syscalls like ioclt() */
	alarm((unsigned int)timeout);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGINT, SIG_IGN);

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	setpriority(PRIO_PROCESS, 0, 0);
	initproctitle(argc, argv);

	/*
	 * -p is used by getty to tell login not to destroy the environment
	 * -f is used to skip a second login authentication
	 * -h is used by other servers to pass the name of the remote
	 *    host to login so that it may be placed in utmp and wtmp
	 */
	while ((c = getopt(argc, argv, "fHh:pV")) != -1)
		switch (c) {
		case 'f':
			cxt.noauth = 1;
			break;

		case 'H':
			cxt.nohost = 1;
			break;

		case 'h':
			if (getuid()) {
				fprintf(stderr,
					_("login: -h for super-user only.\n"));
				exit(EXIT_FAILURE);
			}
			init_remote_info(&cxt, optarg);
			break;

		case 'p':
			cxt.keep_env = 1;
			break;

		case 'V':
			printf(UTIL_LINUX_VERSION);
			return EXIT_SUCCESS;
		case '?':
		default:
			fprintf(stderr, _("usage: login [ -p ] [ -h host ] [ -H ] [ -f username | username ]\n"));
			exit(EXIT_FAILURE);
		}
	argc -= optind;
	argv += optind;

	if (*argv) {
		char *p = *argv;
		cxt.username = xstrdup(p);

		/* wipe name - some people mistype their password here */
		/* (of course we are too late, but perhaps this helps a little ..) */
		while (*p)
			*p++ = ' ';
	}

	for (cnt = get_fd_tabsize() - 1; cnt > 2; cnt--)
		close(cnt);

	setpgrp();	 /* set pgid to pid this means that setsid() will fail */

	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);

	init_tty(&cxt);
	init_loginpam(&cxt);

	/* login -f, then the user has already been authenticated */
	cxt.noauth = cxt.noauth && getuid() == 0 ? 1 : 0;

	if (!cxt.noauth)
		loginpam_auth(&cxt);

	/*
	 * Authentication may be skipped (for example, during krlogin, rlogin,
	 * etc...), but it doesn't mean that we can skip other account checks.
	 * The account could be disabled or password expired (althought
	 * kerberos ticket is valid).         -- [email protected] (22-Feb-2006)
	 */
	loginpam_acct(&cxt);

	if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) {
		warnx(_("\nSession setup problem, abort."));
		syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
		       cxt.username, __FUNCTION__, __LINE__);
		pam_end(cxt.pamh, PAM_SYSTEM_ERR);
		sleepexit(EXIT_FAILURE);
	}

	pwd = cxt.pwd;
	cxt.username = pwd->pw_name;

	/*
	 * Initialize the supplementary group list. This should be done before
	 * pam_setcred because the PAM modules might add groups during
	 * pam_setcred.
	 *
         * For root we don't call initgroups, instead we call setgroups with
	 * group 0. This avoids the need to step through the whole group file,
	 * which can cause problems if NIS, NIS+, LDAP or something similar
	 * is used and the machine has network problems.
	 */
	retcode = pwd->pw_uid ? initgroups(cxt.username, pwd->pw_gid) :	/* user */
			        setgroups(0, NULL);			/* root */
	if (retcode < 0) {
		syslog(LOG_ERR, _("groups initialization failed: %m"));
		warnx(_("\nSession setup problem, abort."));
		pam_end(cxt.pamh, PAM_SYSTEM_ERR);
		sleepexit(EXIT_FAILURE);
	}

	/*
	 * Open PAM session (after successful authentication and account check)
	 */
	loginpam_session(&cxt);

	/* committed to login -- turn off timeout */
	alarm((unsigned int)0);

	endpwent();

	cxt.quiet = get_hushlogin_status(pwd);

	log_utmp(&cxt);
	log_audit(&cxt, 1);
	log_lastlog(&cxt);

	chown_tty(&cxt);

	if (setgid(pwd->pw_gid) < 0 && pwd->pw_gid) {
		syslog(LOG_ALERT, _("setgid() failed"));
		exit(EXIT_FAILURE);
	}

	if (pwd->pw_shell == NULL || *pwd->pw_shell == '\0')
		pwd->pw_shell = _PATH_BSHELL;

	init_environ(&cxt);		/* init $HOME, $TERM ... */

	setproctitle("login", cxt.username);

	log_syslog(&cxt);

	if (!cxt.quiet) {
		motd();

#ifdef LOGIN_STAT_MAIL
		/*
		 * This turns out to be a bad idea: when the mail spool
		 * is NFS mounted, and the NFS connection hangs, the
		 * login hangs, even root cannot login.
		 * Checking for mail should be done from the shell.
		 */
		{
			struct stat st;
			char *mail;

			mail = getenv("MAIL");
			if (mail && stat(mail, &st) == 0 && st.st_size != 0) {
				if (st.st_mtime > st.st_atime)
					printf(_("You have new mail.\n"));
				else
					printf(_("You have mail.\n"));
			}
		}
#endif
	}

	/*
	 * Detach the controlling terminal, fork() and create, new session
	 * and reinilizalize syslog stuff.
	 */
	fork_session(&cxt);

	/* discard permissions last so can't get killed and drop core */
	if (setuid(pwd->pw_uid) < 0 && pwd->pw_uid) {
		syslog(LOG_ALERT, _("setuid() failed"));
		exit(EXIT_FAILURE);
	}

	/* wait until here to change directory! */
	if (chdir(pwd->pw_dir) < 0) {
		warn(_("%s: change directory failed"), pwd->pw_dir);

		if (!getlogindefs_bool("DEFAULT_HOME", 1))
			exit(0);
		if (chdir("/"))
			exit(EXIT_FAILURE);
		pwd->pw_dir = "/";
		printf(_("Logging in with home = \"/\".\n"));
	}

	/* if the shell field has a space: treat it like a shell script */
	if (strchr(pwd->pw_shell, ' ')) {
		buff = xmalloc(strlen(pwd->pw_shell) + 6);

		strcpy(buff, "exec ");
		strcat(buff, pwd->pw_shell);
		childArgv[childArgc++] = "/bin/sh";
		childArgv[childArgc++] = "-sh";
		childArgv[childArgc++] = "-c";
		childArgv[childArgc++] = buff;
	} else {
		char tbuf[PATH_MAX + 2], *p;

		tbuf[0] = '-';
		xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ?
				    p + 1 : pwd->pw_shell), sizeof(tbuf) - 1);

		childArgv[childArgc++] = pwd->pw_shell;
		childArgv[childArgc++] = xstrdup(tbuf);
	}

	childArgv[childArgc++] = NULL;

	execvp(childArgv[0], childArgv + 1);

	if (!strcmp(childArgv[0], "/bin/sh"))
		warn(_("couldn't exec shell script"));
	else
		warn(_("no shell"));

	exit(EXIT_SUCCESS);
}