Ejemplo n.º 1
0
static char *makemsg(char *fname, char **mvec, int mvecsz,
		     size_t *mbufsize, int print_banner)
{
	register int ch, cnt;
	struct stat sbuf;
	FILE *fp;
	char *p, *lbuf, *tmpname, *mbuf;
	long line_max;

	line_max = sysconf(_SC_LINE_MAX);
	lbuf = xmalloc(line_max);

	if ((fp = xfmkstemp(&tmpname, NULL)) == NULL)
		err(EXIT_FAILURE, _("can't open temporary file"));
	unlink(tmpname);
	free(tmpname);

	if (print_banner == TRUE) {
		char *hostname = xgethostname();
		char *whom, *where, *date;
		struct passwd *pw;
		time_t now;

		if (!(whom = getlogin()) || !*whom)
			whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
		if (!whom) {
			whom = "someone";
			warn(_("cannot get passwd uid"));
		}
		where = ttyname(STDOUT_FILENO);
		if (!where) {
			where = "somewhere";
			warn(_("cannot get tty name"));
		} else if (strncmp(where, "/dev/", 5) == 0)
			where += 5;

		time(&now);
		date = xstrdup(ctime(&now));
		date[strlen(date) - 1] = '\0';

		/*
		 * all this stuff is to blank out a square for the message;
		 * we wrap message lines at column 79, not 80, because some
		 * terminals wrap after 79, some do not, and we can't tell.
		 * Which means that we may leave a non-blank character
		 * in column 80, but that can't be helped.
		 */
		/* snprintf is not always available, but the sprintf's here
		   will not overflow as long as %d takes at most 100 chars */
		fprintf(fp, "\r%79s\r\n", " ");
		sprintf(lbuf, _("Broadcast message from %s@%s (%s) (%s):"),
			      whom, hostname, where, date);
		fprintf(fp, "%-79.79s\007\007\r\n", lbuf);
		free(hostname);
		free(date);
	}
	fprintf(fp, "%79s\r\n", " ");

	 if (mvec) {
		/*
		 * Read message from argv[]
		 */
		int i;

		for (i = 0; i < mvecsz; i++) {
			fputs(mvec[i], fp);
			if (i < mvecsz - 1)
				fputc(' ', fp);
		}
		fputc('\r', fp);
		fputc('\n', fp);

	} else {
		/*
		 * read message from <file>
		 */
		if (fname) {
			/*
			 * When we are not root, but suid or sgid, refuse to read files
			 * (e.g. device files) that the user may not have access to.
			 * After all, our invoker can easily do "wall < file"
			 * instead of "wall file".
			 */
			uid_t uid = getuid();
			if (uid && (uid != geteuid() || getgid() != getegid()))
				errx(EXIT_FAILURE, _("will not read %s - use stdin."),
				     fname);

			if (!freopen(fname, "r", stdin))
				err(EXIT_FAILURE, _("cannot open %s"), fname);

		}

		/*
		 * Read message from stdin.
		 */
		while (fgets(lbuf, line_max, stdin)) {
			for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) {
				if (cnt == 79 || ch == '\n') {
					for (; cnt < 79; ++cnt)
						putc(' ', fp);
					putc('\r', fp);
					putc('\n', fp);
					cnt = 0;
				}
				if (ch == '\t')
					cnt += (7 - (cnt % 8));
				if (ch != '\n')
					fputc_careful(ch, fp, '^');
			}
		}
	}
	fprintf(fp, "%79s\r\n", " ");

	free(lbuf);
	rewind(fp);

	if (fstat(fileno(fp), &sbuf))
		err(EXIT_FAILURE, _("stat failed"));

	*mbufsize = (size_t) sbuf.st_size;
	mbuf = xmalloc(*mbufsize);

	if (fread(mbuf, 1, *mbufsize, fp) != *mbufsize)
		err(EXIT_FAILURE, _("fread failed"));

	if (close_stream(fp) != 0)
		errx(EXIT_FAILURE, _("write error"));
	return mbuf;
}
Ejemplo n.º 2
0
/*ARGSUSED*/
int
main(int argc, char *argv[])
{
	char hostname[HOST_NAME_MAX+1], s[BUFSIZ], s1[BUFSIZ], date[256];
	char *p, *style, *nstyle, *ttynam;
	struct itimerval ntimer, otimer;
	int ch, sectimeout, usemine, cnt, tries = 10, backoff = 3;
	const char *errstr;
	struct passwd *pw;
	struct tm *timp;
	time_t curtime;
	login_cap_t *lc;

	sectimeout = TIMEOUT;
	style = NULL;
	usemine = 0;
	no_timeout = 0;

	if (pledge("stdio rpath wpath getpw tty proc exec", NULL) == -1)
		err(1, "pledge");

	if (!(pw = getpwuid(getuid())))
		errx(1, "unknown uid %u.", getuid());

	lc = login_getclass(pw->pw_class);
	if (lc != NULL) {
		/*
		 * We allow "login-tries" attempts to login but start
		 * slowing down after "login-backoff" attempts.
		 */
		tries = (int)login_getcapnum(lc, "login-tries", 10, 10);
		backoff = (int)login_getcapnum(lc, "login-backoff", 3, 3);
	}

	while ((ch = getopt(argc, argv, "a:npt:")) != -1) {
		switch (ch) {
		case 'a':
			if (lc) {
				style = login_getstyle(lc, optarg, "auth-lock");
				if (style == NULL)
					errx(1,
					    "invalid authentication style: %s",
					    optarg);
			}
			usemine = 1;
			break;
		case 't':
			sectimeout = (int)strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				errx(1, "timeout %s: %s", errstr, optarg);
			break;
		case 'p':
			usemine = 1;
			break;
		case 'n':
			no_timeout = 1;
			break;
		default:
			(void)fprintf(stderr,
			    "usage: %s [-np] [-a style] [-t timeout]\n",
			    __progname);
			exit(1);
		}
	}
	timeout.tv_sec = sectimeout * 60;

	gethostname(hostname, sizeof(hostname));
	if (usemine && lc == NULL)
		errx(1, "login class not found");
	if (!(ttynam = ttyname(STDIN_FILENO)))
		errx(1, "not a terminal?");
	curtime = time(NULL);
	nexttime = curtime + (sectimeout * 60);
	timp = localtime(&curtime);
	strftime(date, sizeof(date), "%c", timp);

	if (!usemine) {
		/* get key and check again */
		if (!readpassphrase("Key: ", s, sizeof(s), RPP_ECHO_OFF) ||
		    *s == '\0')
			exit(0);
		/*
		 * Don't need EOF test here, if we get EOF, then s1 != s
		 * and the right things will happen.
		 */
		(void)readpassphrase("Again: ", s1, sizeof(s1), RPP_ECHO_OFF);
		if (strcmp(s1, s)) {
			warnx("\apasswords didn't match.");
			exit(1);
		}
		s[0] = '\0';
	}

	/* set signal handlers */
	(void)signal(SIGINT, hi);
	(void)signal(SIGQUIT, hi);
	(void)signal(SIGTSTP, hi);
	(void)signal(SIGALRM, bye);

	ntimer.it_interval = zerotime;
	ntimer.it_value = timeout;
	if (!no_timeout)
		setitimer(ITIMER_REAL, &ntimer, &otimer);

	/* header info */
	if (no_timeout) {
		(void)fprintf(stderr,
		    "%s: %s on %s. no timeout\ntime now is %s\n",
		    __progname, ttynam, hostname, date);
	} else {
		(void)fprintf(stderr,
		    "%s: %s on %s. timeout in %d minutes\ntime now is %s\n",
		    __progname, ttynam, hostname, sectimeout, date);
	}

	for (cnt = 0;;) {
		if (!readpassphrase("Key: ", s, sizeof(s), RPP_ECHO_OFF) ||
		    *s == '\0') {
			hi(0);
			continue;
		}
		if (usemine) {
			/*
			 * If user entered 's/key' or the style specified via
			 * the '-a' argument, auth_userokay() will prompt
			 * for a new password.  Otherwise, use what we have.
			 */
			if ((strcmp(s, "s/key") == 0 &&
			    (nstyle = login_getstyle(lc, "skey", "auth-lock")))
			    || ((nstyle = style) && strcmp(s, nstyle) == 0))
				p = NULL;
			else
				p = s;
			if (auth_userokay(pw->pw_name, nstyle, "auth-lock", p))
				break;
		} else if (strcmp(s, s1) == 0)
			break;
		(void)putc('\a', stderr);
		cnt %= tries;
		if (++cnt > backoff) {
			sigset_t set, oset;
			sigfillset(&set);
			sigprocmask(SIG_BLOCK, &set, &oset);
			sleep((u_int)((cnt - backoff) * tries / 2));
			sigprocmask(SIG_SETMASK, &oset, NULL);
		}
	}

	exit(0);
}
Ejemplo n.º 3
0
pid_t
forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
{
	int	slave = -1, fd, pipe_fd[2];
	char   *path, dummy;
	pid_t	pid;

	if (pipe(pipe_fd) == -1)
		return (-1);

	if ((*master = open("/dev/ptc", O_RDWR|O_NOCTTY)) == -1)
		goto out;

	if ((path = ttyname(*master)) == NULL)
		goto out;
	if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1)
		goto out;

	switch (pid = fork()) {
	case -1:
		goto out;
	case 0:
		close(*master);

		close(pipe_fd[1]);
		while (read(pipe_fd[0], &dummy, 1) == -1) {
			if (errno != EINTR)
				break;
		}
		close(pipe_fd[0]);

		fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);
		if (fd >= 0) {
			ioctl(fd, TIOCNOTTY, NULL);
			close(fd);
		}

		if (setsid() < 0)
			fatal("setsid");

		fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);
		if (fd >= 0)
			fatalx("open succeeded (failed to disconnect)");

		fd = open(path, O_RDWR);
		if (fd < 0)
			fatal("open failed");
		close(fd);

		fd = open("/dev/tty", O_WRONLY);
		if (fd < 0)
			fatal("open failed");
		close(fd);

		if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1)
			fatal("tcsetattr failed");
		if (ioctl(slave, TIOCSWINSZ, ws) == -1)
			fatal("ioctl failed");

		dup2(slave, 0);
		dup2(slave, 1);
		dup2(slave, 2);
		if (slave > 2)
			close(slave);

		return (0);
	}

	close(slave);

	close(pipe_fd[0]);
	close(pipe_fd[1]);
	return (pid);

out:
	if (*master != -1)
		close(*master);
	if (slave != -1)
		close(slave);

	close(pipe_fd[0]);
	close(pipe_fd[1]);
	return (-1);
}
Ejemplo n.º 4
0
int
main(int argc, char *argv[])
{
	
	int client_sock = -1;
	int client_name_len = sizeof (client_name);
	int request=0;
	
	struct nunetwork_headerstruct *header_buf;
	header_buf = (struct nunetwork_headerstruct*)malloc( sizeof(*header_buf) );
	/********************
         * Don't forget to make pointer to variable cast (*pointer)
         * When using sizeof(). Otherwise it may cost you a week of
	 * debug time.
         *******************/
	

	if (geteuid()) {
		printf("Netustad must be run as root.\n");
		exit(1);
	}
	
	conffile	= (char *)strdup(default_conf_file);
	
	
	/*setlocale (LC_ALL, "");*/
	bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR);
	textdomain ( PACKAGE );
	

	/*******************/
	/* Check Arguments */
	/*******************/
	if (argc==2) {	
			
			if (strcmp(argv[1], "-h") == 0 ||
				strcmp(argv[1], "--help") == 0) {
				printf( gettext("\nnetUstad: Network Ustadi (Network Master)\n"));
				printf( gettext("Copyright (C) 2004   by Ozkan KIRIK\n"));
				printf( gettext("Usage: netustad [options]\n"));
				printf( gettext("\n"));
				printf( "%s:\n", gettext("Options"));
				printf( gettext("\t-h\tShow this help screen\n"));
				printf( gettext("\t-v\tShow version\n"));
				printf
					(gettext("\t-c\tUse following parameter as configuration file"));
				printf("\n");
				exit(0);
			} else if (strcmp(argv[1], "-v") == 0 ||
				   strcmp(argv[1], "--version") == 0) {
				printf(gettext("\nnetUstad: Network Ustadi (Network Master)\n"));
				printf(gettext("Copyright (C) 2004  by Ozkan KIRIK\n\n"));
				printf(gettext("Version: %s\n\n"), NUVERSION);
				exit(0);
			}
				
	} else if (argc == 3 && strcmp(argv[1], "-c") == 0) {
			conffile = strdup(argv[2]);

	}  else if (argc!=1) {
			if (strcmp(argv[1], "-c") == 0) {
				printf (gettext("\nnetUstad: Invalid Number Of Arguments\n\n"));
			} else {
				printf(gettext("\nnetUstad: Invalid Argument\n\n"));
			}
			exit(1);

	}


	/**********************/
	/* Start Main Program */
	/**********************/

	readconfig(conffile);
	if (setlocale (LC_ALL, (const char*) lc_all) == NULL) {
		log_msg(mainlogfile, gettext("setlocale failed\n"), 1);
		printf(gettext("setlocale failed\n"));
	}
	bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR);
	textdomain ( PACKAGE );
	nameoftty = ttyname(0);
	daemonize();

	#ifndef WITHOUT_SSL
        	ssl = nunetwork_init_ssl( nunetwork_init_ctx( cert_file, key_file) );
	#endif

	server_sock = startup(&port);	/* Open Socket & Listen */

	log_msg(mainlogfile, "<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>\n", 0);
	snprintf(log_msg_text, sizeof(log_msg_text)-1, "netUstad-%s\n", NUVERSION);
        log_msg(mainlogfile, log_msg_text, 0);
	snprintf(log_msg_text, sizeof (log_msg_text)-1, "%s",
		 gettext("netUstad is started\n"));
	log_msg(mainlogfile, log_msg_text, 1);
	snprintf(log_msg_text, sizeof (log_msg_text)-1, gettext("\nListening port %d\n"), port);
	log_msg(mainlogfile, log_msg_text, 0);
	log_msg(mainlogfile, gettext("Ready for requests...\n\n"), 0);
	snprintf(log_msg_text, sizeof(log_msg_text)-1, "netUstad-%s\n", NUVERSION);
	log_msg(nameoftty, log_msg_text, 0);
	snprintf(log_msg_text, sizeof (log_msg_text)-1,
		 gettext("\nnetUstad is started\nListening port %d\n"), port);
	log_msg(nameoftty, log_msg_text, 0);

	while (1) {
		client_sock = accept(server_sock,
				     (struct sockaddr *) &client_name,
				     (socklen_t *)&client_name_len);

		if (client_sock == -1)
			continue;
	
		 #ifndef WITHOUT_SSL
		        SSL_set_fd(ssl, client_sock);
		        sslerror = SSL_accept(ssl);
		
		        if ( sslerror <= 0 ) {
		                sslerror= SSL_get_error(ssl, sslerror);
		                ERR_error_string(sslerror, log_msg_text);
		
		                log_msg(mainlogfile, log_msg_text, 1);
				log_msg(mainlogfile, "\n",0);
				SSL_shutdown(ssl);
				SSL_free(ssl);
				close(client_sock);
				ssl = nunetwork_init_ssl(ctx);
				continue;
		        }
			
			request =  nunetwork_getheaders(ssl, header_buf, nu_acceptedheaders); 
			if (request > 0) 
				accept_request(ssl, header_buf);
			else if (request==-2 || request==0)
				bad_request(ssl);
			nunetwork_close(ssl);
		 #else
			request = nunetwork_getheaders(client_sock, header_buf, nu_acceptedheaders);
		        if (request > 0)
				accept_request(client_sock, header_buf);
			else if (request==-2 || request==0 )
				bad_request(ssl);
		 	nunetwork_close(client_sock);
		 #endif
		
	
	
	}
	#ifndef WITHOUT_SSL
		SSL_shutdown(ssl);
		SSL_free(ssl);
		SSL_CTX_free(ctx);
	#else
		close(server_sock);
	#endif


	return (0);
}
Ejemplo n.º 5
0
const char *
Shell::TTYName() const
{
	return ttyname(fFd);
}
Ejemplo n.º 6
0
void
init_io(void)
{
    long ttpgrp;
    static char outbuf[BUFSIZ], errbuf[BUFSIZ];

#ifdef RSH_BUG_WORKAROUND
    int i;
#endif

/* stdout, stderr fully buffered */
#ifdef _IOFBF
    setvbuf(stdout, outbuf, _IOFBF, BUFSIZ);
    setvbuf(stderr, errbuf, _IOFBF, BUFSIZ);
#else
    setbuffer(stdout, outbuf, BUFSIZ);
    setbuffer(stderr, errbuf, BUFSIZ);
#endif

/* This works around a bug in some versions of in.rshd. *
 * Currently this is not defined by default.            */
#ifdef RSH_BUG_WORKAROUND
    if (cmd) {
	for (i = 3; i < 10; i++)
	    close(i);
    }
#endif

    if (shout) {
	fclose(shout);
	shout = 0;
    }
    if (SHTTY != -1) {
	zclose(SHTTY);
	SHTTY = -1;
    }

    /* Make sure the tty is opened read/write. */
    if (isatty(0)) {
	zsfree(ttystrname);
	if ((ttystrname = ztrdup(ttyname(0))))
	    SHTTY = movefd(open(ttystrname, O_RDWR));
    }
    if (SHTTY == -1 && (SHTTY = movefd(open("/dev/tty", O_RDWR))) != -1) {
	zsfree(ttystrname);
	ttystrname = ztrdup("/dev/tty");
    }
    if (SHTTY == -1) {
	zsfree(ttystrname);
	ttystrname = ztrdup("");
    }

    /* We will only use zle if shell is interactive, *
     * SHTTY != -1, and shout != 0                   */
    if (interact && SHTTY != -1) {
	init_shout();
	if(!shout)
	    opts[USEZLE] = 0;
    } else
	opts[USEZLE] = 0;

#ifdef JOB_CONTROL
    /* If interactive, make the shell the foreground process */
    if (opts[MONITOR] && interact && (SHTTY != -1)) {
	attachtty(GETPGRP());
	if ((mypgrp = GETPGRP()) > 0) {
	    while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) {
		sleep(1);
		mypgrp = GETPGRP();
		if (mypgrp == gettygrp())
		    break;
#ifndef __EMX__
		killpg(mypgrp, SIGTTIN);
#endif
		mypgrp = GETPGRP();
	    }
	} else
	    opts[MONITOR] = 0;
    } else
	opts[MONITOR] = 0;
#else
    opts[MONITOR] = 0;
#endif
}
Ejemplo n.º 7
0
Archivo: pty.c Proyecto: gbl/vte
/**
 * vte_pty_child_setup:
 * @pty: a #VtePty
 *
 * FIXMEchpe
 */
void
vte_pty_child_setup (VtePty *pty)
{
        VtePtyPrivate *priv = pty->priv;
	VtePtyChildSetupData *data = &priv->child_setup_data;
	int fd = -1;
	const char *tty = NULL;
        char version[7];

        if (priv->foreign) {
                fd = priv->pty_fd;
        } else {
                /* Save the name of the pty -- we'll need it later to acquire
                * it as our controlling terminal.
                */
                switch (data->mode) {
                        case TTY_OPEN_BY_NAME:
                                tty = data->tty.name;
                                break;
                        case TTY_OPEN_BY_FD:
                                fd = data->tty.fd;
                                tty = ttyname(fd);
                                break;
                }

                _vte_debug_print (VTE_DEBUG_PTY,
                                "Setting up child pty: name = %s, fd = %d\n",
                                        tty ? tty : "(none)", fd);


                /* Try to reopen the pty to acquire it as our controlling terminal. */
                /* FIXMEchpe: why not just use the passed fd in TTY_OPEN_BY_FD mode? */
                if (tty != NULL) {
                        int i = open(tty, O_RDWR);
                        if (i != -1) {
                                if (fd != -1){
                                        close(fd);
                                }
                                fd = i;
                        }
                }
        }

	if (fd == -1)
		_exit (127);

	/* Start a new session and become process-group leader. */
#if defined(HAVE_SETSID) && defined(HAVE_SETPGID)
	_vte_debug_print (VTE_DEBUG_PTY, "Starting new session\n");
	setsid();
	setpgid(0, 0);
#endif

#ifdef TIOCSCTTY
	/* TIOCSCTTY is defined?  Let's try that, too. */
	ioctl(fd, TIOCSCTTY, fd);
#endif

#ifdef HAVE_STROPTS_H
	if (isastream (fd) == 1) {
		if ((ioctl(fd, I_FIND, "ptem") == 0) &&
				(ioctl(fd, I_PUSH, "ptem") == -1)) {
			_exit (127);
		}
		if ((ioctl(fd, I_FIND, "ldterm") == 0) &&
				(ioctl(fd, I_PUSH, "ldterm") == -1)) {
			_exit (127);
		}
		if ((ioctl(fd, I_FIND, "ttcompat") == 0) &&
				(ioctl(fd, I_PUSH, "ttcompat") == -1)) {
			perror ("ioctl (fd, I_PUSH, \"ttcompat\")");
			_exit (127);
		}
	}
#endif

	/* now setup child I/O through the tty */
	if (fd != STDIN_FILENO) {
		if (dup2(fd, STDIN_FILENO) != STDIN_FILENO){
			_exit (127);
		}
	}
	if (fd != STDOUT_FILENO) {
		if (dup2(fd, STDOUT_FILENO) != STDOUT_FILENO){
			_exit (127);
		}
	}
	if (fd != STDERR_FILENO) {
		if (dup2(fd, STDERR_FILENO) != STDERR_FILENO){
			_exit (127);
		}
	}

	/* Close the original slave descriptor, unless it's one of the stdio
	 * descriptors. */
	if (fd != STDIN_FILENO &&
			fd != STDOUT_FILENO &&
			fd != STDERR_FILENO) {
		close(fd);
	}

	/* Reset our signals -- our parent may have done any number of
	 * weird things to them. */
	_vte_pty_reset_signal_handlers();

        /* Now set the TERM environment variable */
        /* FIXME: Setting environment here seems to have no effect, the merged envp2 will override on exec.
         * By the way, we'd need to set the one from there, if any. */
        g_setenv("TERM", VTE_DEFAULT_TERM, TRUE);

        g_snprintf (version, sizeof (version), "%u", VTE_VERSION_NUMERIC);
        g_setenv ("VTE_VERSION", version, TRUE);

	/* Finally call an extra child setup */
	if (data->extra_child_setup) {
		data->extra_child_setup (data->extra_child_setup_data);
	}
}
Ejemplo n.º 8
0
int main(int argc, char **argv)
{
	static struct option long_options[] = {
		{"pidfile\0\tSet pid file name", required_argument, NULL, 'p'},
		{"foreground\0\t\tDon't fork into background", no_argument,
		 NULL, 'f'},
		{"chroot\0\t\tChroot to directory", required_argument, NULL,
		 'C'},
   		{"prompt-prog\0Program to execute for user prompt",
		 required_argument, NULL, 'R'},
		{"version\0\t\t\tShow version information", no_argument, NULL,
		 'V'},
		{"channel\0\tCommunications channel (netlink or miscdev)",
		  required_argument, NULL, 'd'},
		{"help\0\t\t\tShow usage information", no_argument, NULL, 'h'},
		{NULL, 0, NULL, 0}
	};
	static char *short_options = "p:fC:R:Vd:h";
	int long_options_ret;
	struct rlimit core = {0, 0};
	int foreground = 0;
	char *chrootdir = NULL;
	char *tty = NULL;
	uint32_t channel_type = ECRYPTFS_DEFAULT_MESSAGING_TYPE;
	int messaging_type_specified = 0;
	int rc = 0;
	
	while ((long_options_ret = getopt_long(argc, argv, short_options,
					       long_options, NULL)) != -1) {
		switch (long_options_ret) {
		case 'p':
			pidfile = strdup(optarg);
			break;
		case 'f':
			foreground = 1;
			break;
		case 'C':
			chrootdir = strdup(optarg);
			break;
		case 'R':
			prompt_prog = strdup(optarg);
  			break;
		case 'V':
			printf(("%s (%s) %s\n"
				"\n"
				"This is free software.  You may "
				"redistribute copies of it under the "
				"terms of\n"
				"the GNU General Public License "
				"<http://www.gnu.org/licenses/"
				"gpl.html>.\n"
				"There is NO WARRANTY, to the extent "
				"permitted by law.\n"),
			       basename(argv[0]),
			       PACKAGE_NAME,
			       PACKAGE_VERSION);
			exit(0);
			break;
		case 'd':
			messaging_type_specified = 1;
			if (strcmp(optarg, "netlink") == 0)
				channel_type = ECRYPTFS_MESSAGING_TYPE_NETLINK;
			else if (strcmp(optarg, "miscdev") == 0)
				channel_type = ECRYPTFS_MESSAGING_TYPE_MISCDEV;
			break;
		case 'h':
		default:
			usage(basename(argv[0]), long_options,
			      short_options);
			exit(1);
			break;
		}
	}
	openlog(argv[0], LOG_PID | (foreground ? LOG_PERROR : 0), 0);
	if (!messaging_type_specified) {
		uint32_t version;

		rc = ecryptfs_get_version(&version);
		if (rc) {
			syslog(LOG_WARNING, "%s: Unable to retrieve versioning "
			       "info from kernel module; falling back on "
			       "default values\n", __FUNCTION__);
		} else {
			if (version & ECRYPTFS_VERSIONING_MISCDEV)
				channel_type = ECRYPTFS_MESSAGING_TYPE_MISCDEV;
			else
				channel_type = ECRYPTFS_MESSAGING_TYPE_NETLINK;
		}
	}
	tty = ttyname(0); /* We may need the tty name later */
	if (tty != NULL)
		setenv ("TERM_DEVICE", tty, 0);
	if (!foreground)
		daemonize(); /* This will exit if cannot be completed */
	/* Disallow core file; secret values may be in it */
	if (setrlimit(RLIMIT_CORE, &core) == -1) {
		rc = -errno;
		syslog(LOG_ERR, "Cannot setrlimit: %m");
		goto daemon_out;
	}
	if (chrootdir != NULL) {
		if (chroot(chrootdir) == -1) {
			rc = -errno;
			syslog(LOG_ERR, "Failed to chroot to '%s': %m\n",
			       chrootdir);
			goto daemon_out;
		}
		free(chrootdir);
		chrootdir = NULL;
	}
	if (pidfile != NULL) {
		FILE *fp = fopen(pidfile, "w");

		if (fp == NULL) {
			rc = -errno;
			syslog(LOG_ERR, "Failed to open pid file '%s': %m\n",
			       pidfile);
			goto daemon_out;
		}
		fprintf(fp, "%d", (int)getpid());
		fclose(fp);
	}
	if (signal(SIGTERM, sigterm_handler) == SIG_ERR) {
		rc = -ENOTSUP;
		syslog(LOG_ERR, "Failed to attach handler to SIGTERM");
		goto daemon_out;
	}
	if (signal(SIGINT, sigterm_handler) == SIG_ERR) {
		rc = -ENOTSUP;
		syslog(LOG_ERR, "Failed to attach handler to SIGINT");
		goto daemon_out;
	}
 	cryptfs_get_ctx_opts()->prompt = prompt_callback;
	pthread_mutex_init(&mctx_mux, NULL);
	pthread_mutex_lock(&mctx_mux);
	rc = ecryptfs_init_messaging(&mctx, channel_type);
	if (rc) {
		syslog(LOG_ERR, "%s: Failed to initialize messaging; rc = "
		       "[%d]\n", __FUNCTION__, rc);
		pthread_mutex_unlock(&mctx_mux);
		goto daemon_out;
	}
	rc = ecryptfs_send_message(&mctx, NULL, ECRYPTFS_MSG_HELO, 0, 0);
	if (rc) {
		syslog(LOG_ERR, "%s: Error attempting to send message to "
		       "eCryptfs kernel module via transport of type "
		       "[0x%.8x]; rc = [%d]\n", __FUNCTION__, mctx.type, rc);
		pthread_mutex_unlock(&mctx_mux);
		goto daemon_out;
	}
	mctx.state |= ECRYPTFS_MESSAGING_STATE_LISTENING;
	pthread_mutex_unlock(&mctx_mux);
	rc = ecryptfs_run_daemon(&mctx);
	pthread_mutex_lock(&mctx_mux);
	mctx.state &= ~ECRYPTFS_MESSAGING_STATE_LISTENING;
	pthread_mutex_unlock(&mctx_mux);
daemon_out:
	ecryptfsd_exit(&mctx, rc);
	return rc;
}
Ejemplo n.º 9
0
long
ptyint_getpty_ext(int *fd, char *slave, int slavelength, int do_grantpt)
{
#if !defined(HAVE__GETPTY) && !defined(HAVE_OPENPTY)
    char *cp;
    char *p;
    int i,ptynum;
    struct stat stb;
    char slavebuf[1024];
#endif

#ifdef HAVE__GETPTY
    char *slaveret; /*Temporary to hold pointer to slave*/
#endif /*HAVE__GETPTY*/

#ifdef HAVE_OPENPTY
    int slavefd;

    if(openpty(fd, &slavefd, slave, (struct termios *) 0,
         (struct winsize *) 0)) return 1;
    close(slavefd);
    return 0;
#else /*HAVE_OPENPTY*/
#ifdef HAVE__GETPTY
    /* This code is included for Irix; as of version 5.3, Irix has /dev/ptmx,
     * but it fails to work properly; even after calling unlockpt,
     * root gets permission denied opening the pty.
     * The code to support _getpty should be removed if Irix gets working
     * streams ptys in favor of maintaining the least needed code
     * paths.
     */
    if ((slaveret = _getpty(fd, O_RDWR|O_NDELAY, 0600, 0)) == 0) {
	*fd = -1;
	return PTY_GETPTY_NOPTY;
    }
    if (strlen(slaveret) > slavelength - 1) {
	close(*fd);
	*fd = -1;
	return PTY_GETPTY_SLAVE_TOOLONG;
    }
    else strcpy(slave, slaveret);
    return 0;
#else /*HAVE__GETPTY*/
    
    *fd = open("/dev/ptym/clone", O_RDWR|O_NDELAY);	/* HPUX*/
#ifdef HAVE_STREAMS
    if (*fd < 0) *fd = open("/dev/ptmx",O_RDWR|O_NDELAY); /*Solaris*/
#endif
    if (*fd < 0) *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */
    if (*fd < 0) *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */

    if (*fd >= 0) {

#if defined(HAVE_GRANTPT)&&defined(HAVE_STREAMS)
	if (do_grantpt)
	    if (grantpt(*fd) || unlockpt(*fd)) return PTY_GETPTY_STREAMS;
#endif
    
#ifdef HAVE_PTSNAME
	p = ptsname(*fd);
#else
#ifdef	HAVE_TTYNAME
	p = ttyname(*fd);
#else
	/* XXX If we don't have either what do we do */
#endif
#endif
	if (p) {
	    if (strlen(p) > slavelength - 1) {
		    close (*fd);
		    *fd = -1;
		    return PTY_GETPTY_SLAVE_TOOLONG;
	    }
	    strcpy(slave, p);
	    return 0;
	}

	if (fstat(*fd, &stb) < 0) {
	    close(*fd);
	    return PTY_GETPTY_FSTAT;
	}
	ptynum = (int)(stb.st_rdev&0xFF);
	sprintf(slavebuf, "/dev/ttyp%x", ptynum);
	if (strlen(slavebuf) > slavelength - 1) {
	    close(*fd);
	    *fd = -1;
	    return PTY_GETPTY_SLAVE_TOOLONG;
	}
	strncpy(slave, slavebuf, slavelength);
	return 0;
    } else {
    	for (cp = "pqrstuvwxyzPQRST";*cp; cp++) {
	    sprintf(slavebuf,"/dev/ptyXX");
	    slavebuf[sizeof("/dev/pty") - 1] = *cp;
	    slavebuf[sizeof("/dev/ptyp") - 1] = '0';
	    if (stat(slavebuf, &stb) < 0)
		break;
	    for (i = 0; i < 16; i++) {
		slavebuf[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
		*fd = open(slavebuf, O_RDWR);
		if (*fd < 0) continue;

		/* got pty */
		slavebuf[sizeof("/dev/") - 1] = 't';
		if (strlen(slavebuf) > slavelength -1) {
		    close(*fd);
		    *fd = -1;
		    return PTY_GETPTY_SLAVE_TOOLONG;
		}
		strncpy(slave, slavebuf, slavelength);
		return 0;
	    }
	}
	return PTY_GETPTY_NOPTY;
    }
#endif /*HAVE__GETPTY*/
#endif /* HAVE_OPENPTY */
}
Ejemplo n.º 10
0
int				ft_trmgetout(void)
{
    if (g_trm_stdout <= 0)
        g_trm_stdout = open(ttyname(0), O_WRONLY | O_APPEND | O_CREAT);
    return (g_trm_stdout);
}
Ejemplo n.º 11
0
void
makemsg(char *fname)
{
	int cnt;
	wchar_t ch;
	struct tm *lt;
	struct passwd *pw;
	struct stat sbuf;
	time_t now;
	FILE *fp;
	int fd;
	char hostname[MAXHOSTNAMELEN], tmpname[64];
	wchar_t *p, *tmp, lbuf[256], codebuf[13];
	const char *tty;
	const char *whom;
	gid_t egid;

	(void)snprintf(tmpname, sizeof(tmpname), "%s/wall.XXXXXX", _PATH_TMP);
	if ((fd = mkstemp(tmpname)) == -1 || !(fp = fdopen(fd, "r+")))
		err(1, "can't open temporary file");
	(void)unlink(tmpname);

	if (!nobanner) {
		tty = ttyname(STDERR_FILENO);
		if (tty == NULL)
			tty = "no tty";

		if (!(whom = getlogin()))
			whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
		(void)gethostname(hostname, sizeof(hostname));
		(void)time(&now);
		lt = localtime(&now);

		/*
		 * all this stuff is to blank out a square for the message;
		 * we wrap message lines at column 79, not 80, because some
		 * terminals wrap after 79, some do not, and we can't tell.
		 * Which means that we may leave a non-blank character
		 * in column 80, but that can't be helped.
		 */
		(void)fwprintf(fp, L"\r%79s\r\n", " ");
		(void)swprintf(lbuf, sizeof(lbuf)/sizeof(wchar_t),
		    L"Broadcast Message from %s@%s",
		    whom, hostname);
		(void)fwprintf(fp, L"%-79.79S\007\007\r\n", lbuf);
		(void)swprintf(lbuf, sizeof(lbuf)/sizeof(wchar_t),
		    L"        (%s) at %d:%02d %s...", tty,
		    lt->tm_hour, lt->tm_min, lt->tm_zone);
		(void)fwprintf(fp, L"%-79.79S\r\n", lbuf);
	}
	(void)fwprintf(fp, L"%79s\r\n", " ");

	if (fname) {
		egid = getegid();
		setegid(getgid());
		if (freopen(fname, "r", stdin) == NULL)
			err(1, "can't read %s", fname);
		if (setegid(egid) != 0)
			err(1, "setegid failed");
	}
	cnt = 0;
	while (fgetws(lbuf, sizeof(lbuf)/sizeof(wchar_t), stdin)) {
		for (p = lbuf; (ch = *p) != L'\0'; ++p, ++cnt) {
			if (ch == L'\r') {
				putwc(L'\r', fp);
				cnt = 0;
				continue;
			} else if (ch == L'\n') {
				for (; cnt < 79; ++cnt)
					putwc(L' ', fp);
				putwc(L'\r', fp);
				putwc(L'\n', fp);
				break;
			}
			if (cnt == 79) {
				putwc(L'\r', fp);
				putwc(L'\n', fp);
				cnt = 0;
			}
			if (iswprint(ch) || iswspace(ch) || ch == L'\a' || ch == L'\b') {
				putwc(ch, fp);
			} else {
				(void)swprintf(codebuf, sizeof(codebuf)/sizeof(wchar_t), L"<0x%X>", ch);
				for (tmp = codebuf; *tmp != L'\0'; ++tmp) {
					putwc(*tmp, fp);
					if (++cnt == 79) {
						putwc(L'\r', fp);
						putwc(L'\n', fp);
						cnt = 0;
					}
				}
				--cnt;
			}
		}
	}
	(void)fwprintf(fp, L"%79s\r\n", " ");
	rewind(fp);

	if (fstat(fd, &sbuf))
		err(1, "can't stat temporary file");
	mbufsize = sbuf.st_size;
	if (!(mbuf = malloc((u_int)mbufsize)))
		err(1, "out of memory");
	if ((int)fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize)
		err(1, "can't read temporary file");
	(void)close(fd);
}
Ejemplo n.º 12
0
int main(int argc, char* argv[])
{
    int retval;

    const char *user, *tty;
    char hostname[128];
    const char *temp=NULL;
    pam_handle_t *pamh=NULL;
    do {
      if (argc > 1)
	user=argv[1];
      else
	user=getlogin();
      if ((retval = pam_start(basename(argv[0]), user, &conv, &pamh)) != PAM_SUCCESS)
	break;

      gethostname(hostname, sizeof(hostname));
      if ((retval = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS)
	break;
      tty = ttyname(STDERR_FILENO);
      if ((retval = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS)
	break;

/* authenticate the applicant */
        if ((retval = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
	    break;
        if ((retval = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) {
	  if (retval == PAM_NEW_AUTHTOK_REQD) 
	    retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
	  else
	    break;
	}

/* establish the requested credentials */
	if ((retval = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS)
	    break;

	/* authentication succeeded; open a session */
	if ((retval = pam_open_session(pamh, 0)) != PAM_SUCCESS)
	  break;

        printf("Authenticate ok\n");
	pam_get_item(pamh, PAM_SERVICE, (const void **)&temp);
	printf("  service  %s\n", temp);
	pam_get_item(pamh, PAM_USER, (const void **)&temp);
	printf("  user     %s\n", temp);
	pam_get_item(pamh, PAM_AUTHTOK, (const void **)&temp);
	printf("  password %s\n", temp);



    }while (0);

    if (retval != PAM_SUCCESS) {
	printf("Authenticate failed: %s\n", pam_strerror(pamh,retval));
    } else {
      pam_close_session(pamh,0);
    }
    pam_end(pamh,retval);

    return retval == PAM_SUCCESS ? 0:1;
}
Ejemplo n.º 13
0
struct device *
i4b_Create(struct physical *p)
{
  struct i4bdevice *dev;
  int oldflag, dial;
  msg_vr_req_t req;
  telno_t number;

  if (p->fd < 0 || ioctl(p->fd, I4B_RBCH_VR_REQ, &req))
    /* Don't want this */
    return NULL;

  /*
   * We don't bother validating the version.... all versions of i4b that
   * support I4B_RBCH_VR_REQ are fair game :-)
   */

  if (*p->name.full == '\0') {
    physical_SetDevice(p, ttyname(p->fd));
    log_Printf(LogDEBUG, "%s: Input is an i4b version %d.%d.%d isdn "
               "device (%s)\n", p->link.name, req.version, req.release,
               req.step, p->name.full);
    dial = 0;
  } else {
    log_Printf(LogDEBUG, "%s: Opened %s (i4b version %d.%d.%d)\n",
               p->link.name, p->name.full, req.version, req.release, req.step);
    dial = 1;
  }

  /* We're gonna return an i4bdevice (unless something goes horribly wrong) */

  if ((dev = malloc(sizeof *dev)) == NULL) {
    /* Complete failure - parent doesn't continue trying to ``create'' */
    close(p->fd);
    p->fd = -1;
    return NULL;
  }

  memcpy(&dev->dev, &basei4bdevice, sizeof dev->dev);
  memset(&dev->Timer, '\0', sizeof dev->Timer);
  dev->mbits = -1;

  switch (p->cfg.cd.necessity) {
    case CD_VARIABLE:
      dev->dev.cd.delay = p->cfg.cd.delay;
      break;
    case CD_REQUIRED:
      dev->dev.cd = p->cfg.cd;
      break;
    case CD_NOTREQUIRED:
      log_Printf(LogWARN, "%s: Carrier must be set, using ``set cd %d!''\n",
                 p->link.name, dev->dev.cd.delay);
    case CD_DEFAULT:
      break;
  }

  oldflag = fcntl(p->fd, F_GETFL, 0);
  if (oldflag < 0) {
    /* Complete failure - parent doesn't continue trying to ``create'' */

    log_Printf(LogWARN, "%s: Open: Cannot get physical flags: %s\n",
               p->link.name, strerror(errno));
    i4b_Cooked(p);
    close(p->fd);
    p->fd = -1;
    free(dev);
    return NULL;
  } else
    fcntl(p->fd, F_SETFL, oldflag & ~O_NONBLOCK);

  if (dial) {
    strncpy(number, datalink_ChoosePhoneNumber(p->dl), sizeof number - 1);
    number[sizeof number - 1] = '\0';
    if (number[0] == '\0')
      dial = 0;
  }
  if (dial && ioctl(p->fd, I4B_RBCH_DIALOUT, number) == -1) {
    /* Complete failure - parent doesn't continue trying to ``create'' */

    log_Printf(LogWARN, "%s: ioctl(I4B_RBCH_DIALOUT): %s\n",
               p->link.name, strerror(errno));
    i4b_Cooked(p);
    close(p->fd);
    p->fd = -1;
    free(dev);
    return NULL;
  }

  physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNC);

  return &dev->dev;
}
Ejemplo n.º 14
0
int
main(int argc, char *argv[])
{
    struct utmpx ut;
    char *devName;

    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        usageErr("%s username [sleep-time]\n", argv[0]);

    /* Initialize login record for utmp and wtmp files */

    memset(&ut, 0, sizeof(struct utmpx));
    ut.ut_type = USER_PROCESS;          /* This is a user login */
    strncpy(ut.ut_user, argv[1], sizeof(ut.ut_user));
    if (time((time_t *) &ut.ut_tv.tv_sec) == -1)
        errExit("time");                /* Stamp with current time */
    ut.ut_pid = getpid();

    /* Set ut_line and ut_id based on the terminal associated with
       'stdin'. This code assumes terminals named "/dev/[pt]t[sy]*".
       The "/dev/" dirname is 5 characters; the "[pt]t[sy]" filename
       prefix is 3 characters (making 8 characters in all). */

    devName = ttyname(STDIN_FILENO);
    if (devName == NULL)
        errExit("ttyname");
    if (strlen(devName) <= 8)           /* Should never happen */
        fatal("Terminal name is too short: %s", devName);

    strncpy(ut.ut_line, devName + 5, sizeof(ut.ut_line));
    strncpy(ut.ut_id, devName + 8, sizeof(ut.ut_id));

    printf("Creating login entries in utmp and wtmp\n");
    printf("        using pid %ld, line %.*s, id %.*s\n",
            (long) ut.ut_pid, (int) sizeof(ut.ut_line), ut.ut_line,
            (int) sizeof(ut.ut_id), ut.ut_id);

    setutxent();                        /* Rewind to start of utmp file */
    if (pututxline(&ut) == NULL)        /* Write login record to utmp */
        errExit("pututxline");
    updwtmpx(_PATH_WTMP, &ut);          /* Append login record to wtmp */

    /* Sleep a while, so we can examine utmp and wtmp files */

    sleep((argc > 2) ? getInt(argv[2], GN_NONNEG, "sleep-time") : 15);

    /* Now do a "logout"; use values from previously initialized 'ut',
       except for changes below */

    ut.ut_type = DEAD_PROCESS;          /* Required for logout record */
    time((time_t *) &ut.ut_tv.tv_sec);  /* Stamp with logout time */
    memset(&ut.ut_user, 0, sizeof(ut.ut_user));
                                        /* Logout record has null username */

    printf("Creating logout entries in utmp and wtmp\n");
    setutxent();                        /* Rewind to start of utmp file */
    if (pututxline(&ut) == NULL)        /* Overwrite previous utmp record */
        errExit("pututxline");
    updwtmpx(_PATH_WTMP, &ut);          /* Append logout record to wtmp */

    endutxent();
    exit(EXIT_SUCCESS);
}
Ejemplo n.º 15
0
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
{
#if defined(HAVE_OPENPTY) || defined(BSD4_4)
	/* openpty(3) exists in OSF/1 and some other os'es */
	char *name;
	int i;

	i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
	if (i < 0) {
		error("openpty: %.100s", strerror(errno));
		return 0;
	}
	name = ttyname(*ttyfd);
	if (!name)
		fatal("openpty returns device for which ttyname fails.");

	strlcpy(namebuf, name, namebuflen);	/* possible truncation */
	return 1;
#else /* HAVE_OPENPTY */
#ifdef HAVE__GETPTY
	/*
	 * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
	 * pty's automagically when needed
	 */
	char *slave;

	slave = _getpty(ptyfd, O_RDWR, 0622, 0);
	if (slave == NULL) {
		error("_getpty: %.100s", strerror(errno));
		return 0;
	}
	strlcpy(namebuf, slave, namebuflen);
	/* Open the slave side. */
	*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
	if (*ttyfd < 0) {
		error("%.200s: %.100s", namebuf, strerror(errno));
		close(*ptyfd);
		return 0;
	}
	return 1;
#else /* HAVE__GETPTY */
#if defined(HAVE_DEV_PTMX)
	/*
	 * This code is used e.g. on Solaris 2.x.  (Note that Solaris 2.3
	 * also has bsd-style ptys, but they simply do not work.)
	 */
	int ptm;
	char *pts;
	mysig_t old_signal;

	ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY);
	if (ptm < 0) {
		error("/dev/ptmx: %.100s", strerror(errno));
		return 0;
	}
	old_signal = mysignal(SIGCHLD, SIG_DFL);
	if (grantpt(ptm) < 0) {
		error("grantpt: %.100s", strerror(errno));
		return 0;
	}
	mysignal(SIGCHLD, old_signal);
	if (unlockpt(ptm) < 0) {
		error("unlockpt: %.100s", strerror(errno));
		return 0;
	}
	pts = ptsname(ptm);
	if (pts == NULL)
		error("Slave pty side name could not be obtained.");
	strlcpy(namebuf, pts, namebuflen);
	*ptyfd = ptm;

	/* Open the slave side. */
	*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
	if (*ttyfd < 0) {
		error("%.100s: %.100s", namebuf, strerror(errno));
		close(*ptyfd);
		return 0;
	}
#ifndef HAVE_CYGWIN
	/*
	 * Push the appropriate streams modules, as described in Solaris pts(7).
	 * HP-UX pts(7) doesn't have ttcompat module.
	 */
	if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
		error("ioctl I_PUSH ptem: %.100s", strerror(errno));
	if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
		error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
#ifndef __hpux
	if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
		error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
#endif
#endif
	return 1;
#else /* HAVE_DEV_PTMX */
#ifdef HAVE_DEV_PTS_AND_PTC
	/* AIX-style pty code. */
	const char *name;

	*ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY);
	if (*ptyfd < 0) {
		error("Could not open /dev/ptc: %.100s", strerror(errno));
		return 0;
	}
	name = ttyname(*ptyfd);
	if (!name)
		fatal("Open of /dev/ptc returns device for which ttyname fails.");
	strlcpy(namebuf, name, namebuflen);
	*ttyfd = open(name, O_RDWR | O_NOCTTY);
	if (*ttyfd < 0) {
		error("Could not open pty slave side %.100s: %.100s",
		    name, strerror(errno));
		close(*ptyfd);
		return 0;
	}
	return 1;
#else /* HAVE_DEV_PTS_AND_PTC */
#ifdef _UNICOS
	char buf[64];
	int i;
	int highpty;

#ifdef _SC_CRAY_NPTY
	highpty = sysconf(_SC_CRAY_NPTY);
	if (highpty == -1)
		highpty = 128;
#else
	highpty = 128;
#endif

	for (i = 0; i < highpty; i++) {
		snprintf(buf, sizeof(buf), "/dev/pty/%03d", i);
		*ptyfd = open(buf, O_RDWR|O_NOCTTY);
		if (*ptyfd < 0)
			continue;
		snprintf(namebuf, namebuflen, "/dev/ttyp%03d", i);
		/* Open the slave side. */
		*ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
		if (*ttyfd < 0) {
			error("%.100s: %.100s", namebuf, strerror(errno));
			close(*ptyfd);
			return 0;
		}
		return 1;
	}
	return 0;
#else
	/* BSD-style pty code. */
	char buf[64];
	int i;
	const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
	const char *ptyminors = "0123456789abcdef";
	int num_minors = strlen(ptyminors);
	int num_ptys = strlen(ptymajors) * num_minors;
	struct termios tio;

	for (i = 0; i < num_ptys; i++) {
		snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
			 ptyminors[i % num_minors]);
		snprintf(namebuf, namebuflen, "/dev/tty%c%c",
		    ptymajors[i / num_minors], ptyminors[i % num_minors]);

		*ptyfd = open(buf, O_RDWR | O_NOCTTY);
		if (*ptyfd < 0) {
			/* Try SCO style naming */
			snprintf(buf, sizeof buf, "/dev/ptyp%d", i);
			snprintf(namebuf, namebuflen, "/dev/ttyp%d", i);
			*ptyfd = open(buf, O_RDWR | O_NOCTTY);
			if (*ptyfd < 0)
				continue;
		}

		/* Open the slave side. */
		*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
		if (*ttyfd < 0) {
			error("%.100s: %.100s", namebuf, strerror(errno));
			close(*ptyfd);
			return 0;
		}
		/* set tty modes to a sane state for broken clients */
		if (tcgetattr(*ptyfd, &tio) < 0)
			log("Getting tty modes for pty failed: %.100s", strerror(errno));
		else {
			tio.c_lflag |= (ECHO | ISIG | ICANON);
			tio.c_oflag |= (OPOST | ONLCR);
			tio.c_iflag |= ICRNL;

			/* Set the new modes for the terminal. */
			if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0)
				log("Setting tty modes for pty failed: %.100s", strerror(errno));
		}

		return 1;
	}
	return 0;
#endif /* CRAY */
#endif /* HAVE_DEV_PTS_AND_PTC */
#endif /* HAVE_DEV_PTMX */
#endif /* HAVE__GETPTY */
#endif /* HAVE_OPENPTY */
}
Ejemplo n.º 16
0
QgsGrassShell::QgsGrassShell( QgsGrassTools *tools,
                              QTabWidget * parent, const char * name ):
    QDialog( parent ), QgsGrassShellBase(), mTools( tools )
{
  mValid = false;
  mSkipLines = 2;
  mTabWidget = parent;

#ifdef WIN32
  QMessageBox::warning( 0, "Warning",
                        "GRASS Shell is not supported on Windows." );
  return;
#else

  setupUi( this );

  QGridLayout *layout = new QGridLayout( mTextFrame, 1, 1 );
  mText = new QgsGrassShellText( this, mTextFrame );
  layout->addWidget( mText, 0, 0 );
  mText->show();

  connect( mCloseButton, SIGNAL( clicked() ), this, SLOT( closeShell() ) );

  mFont = QFont( "Courier", 10 );

  mAppDir = mTools->appDir();

#ifndef Q_WS_MAC
  // Qt4.3.2/Mac Q3TextEdit readOnly property causes keys to be processed as keyboard actions
  mText->setReadOnly( TRUE );
#endif
  //mText->setFocusPolicy ( QWidget::NoFocus ); // To get key press directly

#ifndef HAVE_OPENPTY
  mText->append( "GRASS shell is not supported" );
  return;
#endif

  // TODO set cursor IbeamCursor
  // This does not work - the cursor is used for scrollbars -> disabled
  //mText->setCursor ( QCursor(Qt::IbeamCursor) );
  mParagraph = -1; // first will be 0
  mIndex = -1;

  mNewLine = true;

  for ( int i = 0; i < ModeCount; i++ )
  {
    resetMode( i );
  }

  int uid;
  seteuid( uid = getuid() ); /* Run unprivileged */

  // Get and open pseudo terminal
  // Note: 0 (stdin), 1 (stdout) or 2 (stderr)
  int fdSlave; // slave file descriptor
  seteuid( 0 );
  int ret =  openpty( &mFdMaster, &fdSlave, NULL, NULL, NULL );
  if ( ret != 0 )
  {
    QMessageBox::warning( 0, "Warning", "Cannot open pseudo terminal" );
    return;
  }
  fchown( fdSlave, uid, ( gid_t ) - 1 );
  fchmod( fdSlave, S_IRUSR | S_IWUSR );
  seteuid( uid );

  QgsDebugMsg( QString( "mFdMaster = %1" ).arg( mFdMaster ) );
  QgsDebugMsg( QString( "fdSlave = %1" ).arg( fdSlave ) );

  fcntl( mFdMaster, F_SETFL, O_NDELAY );
  //fcntl( fdSlave, F_SETFL, O_NDELAY); // enable?

  QString slaveName = ttyname( fdSlave );
  QgsDebugMsg( QString( "master ttyname = %1" ).arg( ttyname( mFdMaster ) ) );
  QgsDebugMsg( QString( "slave ttyname = %1" ).arg( ttyname( fdSlave ) ) );

  //::close( fdSlave ); // -> crash

  // Fork slave and open shell
  int pid = fork();
  QgsDebugMsg( QString( "pid = %1" ).arg( pid ) );
  if ( pid == -1 )
  {
    QMessageBox::warning( 0, "Warning", "Cannot fork shell" );
    return;
  }

  // Child - slave
  if ( pid == 0 )
  {
    QgsDebugMsg( "child ->" );

    // TODO close all opened file descriptors - close(0)???
    ::close( mFdMaster );

    //::close( fdSlave ); // -> freeze

    setsid();
    seteuid( 0 );

    int fd = ::open(( char* ) slaveName.ascii(), O_RDWR );
    if ( fd < 0 )
    {
      QMessageBox::warning( 0, "Warning", "Cannot open slave file "
                            "in child process" );
      return;
    }

    fchown( fd, uid, ( gid_t ) - 1 );
    fchmod( fd, S_IRUSR | S_IWUSR );
    setuid( uid );

    dup2( fd, 0 ); /* stdin */
    dup2( fd, 1 ); /* stdout */
    dup2( fd, 2 ); /* stderr */

    // TODO: test if shell is available
    QString shell = ( getenv( "SHELL" ) );
    if ( shell.isEmpty() )
    {
      shell = "/bin/bash";
    }

    const char *norc = "";
    QFileInfo si( shell );
    if ( si.fileName() ==  "bash" || si.fileName() ==  "sh" )
    {
      norc = "--norc";
    }
    else if ( si.fileName() ==  "tcsh" || si.fileName() ==  "csh" )
    {
      norc = "-f";
    }

    // Warning: execle + --norc will not inherit not given variables
    // -> overwrite here
    const char *env = "GRASS_MESSAGE_FORMAT=gui";
    char *envstr = new char[strlen( env )+1];
    strcpy( envstr, env );
    putenv( envstr );

    putenv(( char * ) "GISRC_MODE_MEMORY" );  // unset

    env = "PS1=GRASS > ";
    envstr = new char[strlen( env )+1];
    strcpy( envstr, env );
    putenv( envstr );

    env = "TERM=vt100";
    envstr = new char[strlen( env )+1];
    strcpy( envstr, env );
    putenv( envstr );

    //char *envar[] = { "PS1=GRASS > ", "TERM=vt100", "GISRC_MODE_MEMORY=",
    //                  "GRASS_MESSAGE_FORMAT=gui", (char *)0 };

    //execle ( (char*)shell.ascii(), (char *)si.fileName().ascii(),
    //         norc, (char *) 0, envar);
    execl(( char* )shell.ascii(), ( char * )si.fileName().ascii(),
          norc, ( char * ) 0 );

    // Failed (QMessageBox here does not work)
    fprintf( stderr, "GRASS_INFO_ERROR(1,1): Cannot start shell %s\n",
             ( char* )shell.ascii() );
    exit( 1 );
  }

  mPid = pid;

  // Create socket notifier
  mOutNotifier = new QSocketNotifier( mFdMaster, QSocketNotifier::Read, this );

  QObject::connect( mOutNotifier, SIGNAL( activated( int ) ),
                    this, SLOT( readStdout( int ) ) );

  // Set tab stops ???
  mTabStop.resize( 200 );
  for ( int i = 0 ; i * 8 < ( int )mTabStop.size(); i++ )
  {
    mTabStop[i*8] = true;
  }

  // Set trap to write history on SIGUSR1
  //QString trap = "trap 'history -w' SIGUSR1\015\012";
  QString trap = "trap 'history -w' SIGUSR1\015";
  write( mFdMaster, trap.ascii(), trap.length() );
  mText->clear();

  resizeTerminal();
  mValid = true;
#endif // !WIN32
}
Ejemplo n.º 17
0
int
cray_setup (uid_t uid, char *username, const char *command)
{
	extern struct udb *getudb();
	extern char *setlimits();

	int err;			/* error return */
	time_t system_time;		/* current system clock */
	time_t expiration_time;		/* password expiration time */
	int maxattempts;		/* maximum no. of failed login attempts */
	int SecureSys;			/* unicos security flag */
	int minslevel = 0;		/* system minimum security level */
	int i, j;
	int valid_acct = -1;		/* flag for reading valid acct */
	char acct_name[MAXACID] = { "" }; /* used to read acct name */
	struct jtab jtab;		/* Job table struct */
	struct udb ue;			/* udb entry for logging-in user */
	struct udb *up;			/* pointer to UDB entry */
	struct secstat secinfo;		/* file  security attributes */
	struct servprov init_info;	/* used for sesscntl() call */
	int jid;			/* job ID */
	int pid;			/* process ID */
	char *sr;			/* status return from setlimits() */
	char *ttyn = NULL;		/* ttyname or command name*/
	char hostname[MAXHOSTNAMELEN];
	/* passwd stuff for ia_user */
	passwd_t pwdacm, pwddialup, pwdudb, pwdwal, pwddce;
	ia_user_ret_t uret;		/* stuff returned from ia_user */
	ia_user_t usent;		/* ia_user main structure */
	int ia_rcode;			/* ia_user return code */
	ia_failure_t fsent;		/* ia_failure structure */
	ia_failure_ret_t fret;		/* ia_failure return stuff */
	ia_success_t ssent;		/* ia_success structure */
	ia_success_ret_t sret;		/* ia_success return stuff */
	int ia_mlsrcode;		/* ia_mlsuser return code */
	int secstatrc;			/* [f]secstat return code */

	if (SecureSys = (int)sysconf(_SC_CRAY_SECURE_SYS)) {
		getsysv(&sysv, sizeof(struct sysv));
		minslevel = sysv.sy_minlvl;
		if (getusrv(&usrv) < 0)
			fatal("getusrv() failed, errno = %d", errno);
	}
	hostname[0] = '\0';
	strlcpy(hostname,
	   (char *)get_canonical_hostname(options.use_dns),
	   MAXHOSTNAMELEN);
	/*
	 *  Fetch user's UDB entry.
	 */
	getsysudb();
	if ((up = getudbnam(username)) == UDB_NULL)
		fatal("cannot fetch user's UDB entry");

	/*
	 *  Prevent any possible fudging so perform a data
	 *  safety check and compare the supplied uid against
	 *  the udb's uid.
	 */
	if (up->ue_uid != uid)
		fatal("IA uid missmatch");
	endudb();

	if ((jid = getjtab(&jtab)) < 0) {
		debug("getjtab");
		return(-1);
	}
	pid = getpid();
	ttyn = ttyname(0);
	if (SecureSys) {
		if (ttyn != NULL)
			secstatrc = secstat(ttyn, &secinfo);
		else
			secstatrc = fsecstat(1, &secinfo);

		if (secstatrc == 0)
			debug("[f]secstat() successful");
		else
			fatal("[f]secstat() error, rc = %d", secstatrc);
	}
	if ((ttyn == NULL) && ((char *)command != NULL))
		ttyn = (char *)command;
	/*
	 *  Initialize all structures to call ia_user
	 */
	usent.revision = 0;
	usent.uname = username;
	usent.host = hostname;
	usent.ttyn = ttyn;
	usent.caller = IA_SSHD; 
	usent.pswdlist = &pwdacm;
	usent.ueptr = &ue;
	usent.flags = IA_INTERACTIVE | IA_FFLAG;
	pwdacm.atype = IA_SECURID;
	pwdacm.pwdp = NULL;
	pwdacm.next = &pwdudb;

	pwdudb.atype = IA_UDB;
	pwdudb.pwdp = NULL;
	pwdudb.next = &pwddce;

	pwddce.atype = IA_DCE;
	pwddce.pwdp = NULL;
	pwddce.next = &pwddialup;

	pwddialup.atype = IA_DIALUP;
	pwddialup.pwdp = NULL;
	/* pwddialup.next = &pwdwal; */
	pwddialup.next = NULL;

	pwdwal.atype = IA_WAL;
	pwdwal.pwdp = NULL;
	pwdwal.next = NULL;

	uret.revision = 0;
	uret.pswd = NULL;
	uret.normal = 0;

	ia_rcode = ia_user(&usent, &uret);
	switch (ia_rcode) {
	/*
	 *  These are acceptable return codes from ia_user()
	 */
	case IA_UDBWEEK:        /* Password Expires in 1 week */
		expiration_time = ue.ue_pwage.time + ue.ue_pwage.maxage;
		printf ("WARNING - your current password will expire %s\n",
		ctime((const time_t *)&expiration_time));
		break;
	case IA_UDBEXPIRED:
		if (ttyname(0) != NULL) {
			/* Force a password change */
			printf("Your password has expired; Choose a new one.\n");
			execl("/bin/passwd", "passwd", username, 0);
			exit(9);
			}
		break;
	case IA_NORMAL:         /* Normal Return Code */
		break;
	case IA_BACKDOOR:
		/* XXX: can we memset it to zero here so save some of this */
		strlcpy(ue.ue_name, "root", sizeof(ue.ue_name));
		strlcpy(ue.ue_dir, "/", sizeof(ue.ue_dir));
		strlcpy(ue.ue_shell, "/bin/sh", sizeof(ue.ue_shell));

		ue.ue_passwd[0] = '\0';
		ue.ue_age[0] = '\0';
		ue.ue_comment[0] = '\0';
		ue.ue_loghost[0] = '\0';
		ue.ue_logline[0] = '\0';

		ue.ue_uid = -1;
		ue.ue_nice[UDBRC_INTER] = 0;

		for (i = 0; i < MAXVIDS; i++)
			ue.ue_gids[i] = 0;

		ue.ue_logfails = 0;
		ue.ue_minlvl = ue.ue_maxlvl = ue.ue_deflvl = minslevel;
		ue.ue_defcomps = 0;
		ue.ue_comparts = 0;
		ue.ue_permits = 0;
		ue.ue_trap = 0;
		ue.ue_disabled = 0;
		ue.ue_logtime = 0;
		break;
	case IA_CONSOLE:        /* Superuser not from Console */
	case IA_TRUSTED:	/* Trusted user */
		if (options.permit_root_login > PERMIT_NO)
			break;	/* Accept root login */
	default:
	/*
	 *  These are failed return codes from ia_user()
	 */
		switch (ia_rcode) 
		{
		case IA_BADAUTH:
			printf("Bad authorization, access denied.\n");
			break;
		case IA_DISABLED:
			printf("Your login has been disabled. Contact the system ");
			printf("administrator for assistance.\n");
			break;
		case IA_GETSYSV:
			printf("getsysv() failed - errno = %d\n", errno);
			break;
		case IA_MAXLOGS:
			printf("Maximum number of failed login attempts exceeded.\n");
			printf("Access denied.\n");
			break;
		case IA_UDBPWDNULL:
			if (SecureSys)
				printf("NULL Password not allowed on MLS systems.\n");
			break;
		default:
			break;
		}

		/*
		 *  Authentication failed.
		 */
		printf("sshd: Login incorrect, (0%o)\n",
		    ia_rcode-IA_ERRORCODE);

		/*
		 *  Initialize structure for ia_failure
		 *  which will exit.
		 */
		fsent.revision = 0;
		fsent.uname = username;
		fsent.host = hostname;
		fsent.ttyn = ttyn;
		fsent.caller = IA_SSHD;
		fsent.flags = IA_INTERACTIVE;
		fsent.ueptr = &ue;
		fsent.jid = jid;
		fsent.errcode = ia_rcode;
		fsent.pwdp = uret.pswd;
		fsent.exitcode = 1;

		fret.revision = 0;
		fret.normal = 0;

		/*
		*  Call ia_failure because of an IA failure.
		*  There is no return because ia_failure exits.
		*/
		ia_failure(&fsent, &fret);

		exit(1); 
	}

	ia_mlsrcode = IA_NORMAL;
	if (SecureSys) {
		debug("calling ia_mlsuser()");
		ia_mlsrcode = ia_mlsuser(&ue, &secinfo, &usrv, NULL, 0);
	}
	if (ia_mlsrcode != IA_NORMAL) {
		printf("sshd: Login incorrect, (0%o)\n",
		    ia_mlsrcode-IA_ERRORCODE);
		/*
		 *  Initialize structure for ia_failure
		 *  which will exit.
		 */
		fsent.revision = 0;
		fsent.uname = username;
		fsent.host = hostname;
		fsent.ttyn = ttyn;
		fsent.caller = IA_SSHD;
		fsent.flags = IA_INTERACTIVE;
		fsent.ueptr = &ue;
		fsent.jid  = jid;
		fsent.errcode = ia_mlsrcode;
		fsent.pwdp = uret.pswd;
		fsent.exitcode = 1;
		fret.revision = 0;
		fret.normal = 0;

		/*
		 *  Call ia_failure because of an IA failure.
		 *  There is no return because ia_failure exits.
		 */
		ia_failure(&fsent,&fret);
		exit(1); 
	}

	/* Provide login status information */
	if (options.print_lastlog && ue.ue_logtime != 0) {
		printf("Last successful login was : %.*s ", 19,
		    (char *)ctime(&ue.ue_logtime));

		if (*ue.ue_loghost != '\0') {
			printf("from %.*s\n", sizeof(ue.ue_loghost),
			    ue.ue_loghost);
		} else {
			printf("on %.*s\n", sizeof(ue.ue_logline),
			    ue.ue_logline);
		}

		if (SecureSys && (ue.ue_logfails != 0)) {
			printf("  followed by %d failed attempts\n",
			    ue.ue_logfails);
		}
	}

	/*
	 * Call ia_success to process successful I/A.
	 */
	ssent.revision = 0;
	ssent.uname = username;
	ssent.host = hostname;
	ssent.ttyn = ttyn;
	ssent.caller = IA_SSHD;
	ssent.flags = IA_INTERACTIVE;
	ssent.ueptr = &ue;
	ssent.jid = jid;
	ssent.errcode = ia_rcode;
	ssent.us = NULL;
	ssent.time = 1;	/* Set ue_logtime */

	sret.revision = 0;
	sret.normal = 0;

	ia_success(&ssent, &sret);

	/*
	 * Query for account, iff > 1 valid acid & askacid permbit
	 */
	if (((ue.ue_permbits & PERMBITS_ACCTID) ||
	    (ue.ue_acids[0] >= 0) && (ue.ue_acids[1] >= 0)) &&
	    ue.ue_permbits & PERMBITS_ASKACID) {
		if (ttyname(0) != NULL) {
			debug("cray_setup: ttyname true case, %.100s", ttyname);
			while (valid_acct == -1) {
				printf("Account (? for available accounts)"
				    " [%s]: ", acid2nam(ue.ue_acids[0]));
				fgets(acct_name, MAXACID, stdin);
				switch (acct_name[0]) {
				case EOF:
					exit(0);
					break;
				case '\0':
					valid_acct = ue.ue_acids[0];
					strlcpy(acct_name, acid2nam(valid_acct), MAXACID);
					break;
				case '?':
					/* Print the list 3 wide */
					for (i = 0, j = 0; i < MAXVIDS; i++) {
						if (ue.ue_acids[i] == -1) {
							printf("\n");
							break;
						}
						if (++j == 4) {
							j = 1;
							printf("\n");
						}
						printf(" %s",
						    acid2nam(ue.ue_acids[i]));
					}
					if (ue.ue_permbits & PERMBITS_ACCTID) {
						printf("\"acctid\" permbit also allows"
						    " you to select any valid "
						    "account name.\n");
					}
					printf("\n");
					break;
				default:
					valid_acct = nam2acid(acct_name);
					if (valid_acct == -1) 
						printf(
						    "Account id not found for"
						    " account name \"%s\"\n\n",
						    acct_name);
					break;
				}
				/*
				 * If an account was given, search the user's
				 * acids array to verify they can use this account.
				 */
				if ((valid_acct != -1) &&
				    !(ue.ue_permbits & PERMBITS_ACCTID)) {
					for (i = 0; i < MAXVIDS; i++) {
						if (ue.ue_acids[i] == -1)
							break;
						if (valid_acct == ue.ue_acids[i])
							break;
					}
					if (i == MAXVIDS ||
					    ue.ue_acids[i] == -1) {
						fprintf(stderr, "Cannot set"
						    " account name to "
						    "\"%s\", permission "
						    "denied\n\n", acct_name);
						valid_acct = -1;
					}
				}
			}
		} else {
			/*
			 * The client isn't connected to a terminal and can't
			 * respond to an acid prompt.  Use default acid.
			 */
			debug("cray_setup: ttyname false case, %.100s",
			    ttyname);
			valid_acct = ue.ue_acids[0];
		}
	} else {
		/*
		 * The user doesn't have the askacid permbit set or
		 * only has one valid account to use.
		 */
		valid_acct = ue.ue_acids[0];
	}
	if (acctid(0, valid_acct) < 0) {
		printf ("Bad account id: %d\n", valid_acct);
		exit(1);
	}

	/* 
	 * Now set shares, quotas, limits, including CPU time for the 
	 * (interactive) job and process, and set up permissions 
	 * (for chown etc), etc.
	 */
	if (setshares(ue.ue_uid, valid_acct, printf, 0, 0)) {
		printf("Unable to give %d shares to <%s>(%d/%d)\n",
		    ue.ue_shares, ue.ue_name, ue.ue_uid, valid_acct);
		exit(1);
	}

	sr = setlimits(username, C_PROC, pid, UDBRC_INTER);
	if (sr != NULL) {
		debug("%.200s", sr);
		exit(1);
	}
	sr = setlimits(username, C_JOB, jid, UDBRC_INTER);
	if (sr != NULL) {
		debug("%.200s", sr);
		exit(1);
	}
	/*
	 * Place the service provider information into
	 * the session table (Unicos) or job table (Unicos/mk).
	 * There exist double defines for the job/session table in
	 * unicos/mk (jtab.h) so no need for a compile time switch.
	 */
	memset(&init_info, '\0', sizeof(init_info));
	init_info.s_sessinit.si_id = URM_SPT_LOGIN;
	init_info.s_sessinit.si_pid = getpid();
	init_info.s_sessinit.si_sid = jid;
	sesscntl(0, S_SETSERVPO, (int)&init_info);

	/*
	 * Set user and controlling tty security attributes.
	 */
	if (SecureSys) {
		if (setusrv(&usrv) == -1) {
			debug("setusrv() failed, errno = %d",errno);
			exit(1);
		}
	}

	return (0);
}
Ejemplo n.º 18
0
/**
 * main() - IUCV TTY program startup
 */
int main(int argc, char *argv[])
{
    struct iucvterm_cfg	conf;		/* program configuration */
    struct sockaddr_iucv	saddr, caddr;	/* IUCV socket address info */
    char 			client_host[9];	/* client guest name */
    int 			server, client;	/* socket file descriptors */
    int 			master, slave;	/* pre-allocated PTY fds */
    struct sigaction	sigact;		/* signal handler */
    int 			rc;
    socklen_t		len;


    /* gettext initialization */
    gettext_init();

    /* parse command line arguments */
    parse_options(PROG_IUCV_TTY, &conf, argc, argv);

    /* create server socket... */
    server = iucvtty_socket(&saddr, NULL, conf.service);
    if (server == -1) {
        print_error((errno == EAFNOSUPPORT)
                    ? N_("The AF_IUCV address family is not available")
                    : N_("Creating the AF_IUCV socket failed"));
        return 1;
    }
    if (bind(server, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) {
        print_error("Binding the AF_IUCV socket failed");
        close(server);
        return 1;
    }
    if (listen(server, 1) == -1) {
        print_error("Listening for incoming connections failed");
        close(server);
        return 1;
    }

    /* pre-allocate PTY master/slave file descriptors */
    if (openpty(&master, &slave, NULL, NULL, NULL)) {
        print_error("Opening a new PTY master/slave device pair failed");
        close(server);
        return 1;
    }

    /* set close-on-exec for file descriptors */
    fcntl(master, F_SETFD, FD_CLOEXEC);
    fcntl(server, F_SETFD, FD_CLOEXEC);

    /* syslog */
    openlog(SYSLOG_IDENT, LOG_PID, LOG_AUTHPRIV);
    syslog(LOG_INFO, "Listening on terminal ID: %s, using pts device: %s",
           conf.service, ttyname(slave));

    rc = 0;
    len = sizeof(struct sockaddr_iucv);
    /* accept a new client connection */
    client = accept(server, (struct sockaddr *) &caddr, &len);
    if (client == -1) {
        print_error("An incoming connection could not be accepted");
        rc = 2;
        goto exit_on_error;
    }

    /* check if client is allowed to connect */
    userid_cpy(client_host, caddr.siucv_user_id);
    if (is_client_allowed(client_host, &conf)) {
        iucvtty_tx_error(client, ERR_NOT_AUTHORIZED);
        syslog(LOG_WARNING, "Rejected client connection from %s; "
               "Client is not allowed to connect.",
               client_host);
        rc = 3;

    } else { /* client is allowed to connect */
        syslog(LOG_INFO, "Accepted client connection from %s",
               client_host);
        /* set close-on-exec for client socket */
        fcntl(client, F_SETFD, FD_CLOEXEC);
        /* close server socket */
        close(server);

        /* setup signal handler to notify shutdown signal */
        sigemptyset(&sigact.sa_mask);
        sigact.sa_flags = SA_RESTART;
        sigact.sa_handler = sig_handler;
        if (sigaction(SIGCHLD, &sigact, NULL)
                || sigaction(SIGTERM, &sigact, NULL)
                || sigaction(SIGINT,  &sigact, NULL)
                || sigaction(SIGPIPE, &sigact, NULL)) {
            print_error("Registering a signal handler failed");
            rc = 4;
            goto exit_on_error;
        }

        /* handle client terminal connection */
        rc = iucvtty_worker(client, master, slave, &conf);
    }

    close(client);

exit_on_error:
    close(slave);
    close(master);
    closelog();

    return rc;
}
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
{
#if defined(HAVE_OPENPTY)
	/* exists in recent (4.4) BSDs and OSF/1 */
	char *name;
	int i;

#if !defined(HAVE_TTYNAME)
	i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
#else
	i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
#endif
	if (i < 0) {
		dropbear_log(LOG_WARNING, 
				"pty_allocate: openpty: %.100s", strerror(errno));
		return 0;
	}
#if defined(HAVE_TTYNAME)
	name_ptr = ttyname(*ttyfd);
	if (!name) {
		dropbear_exit("ttyname fails for openpty device");
	}

	strlcpy(namebuf, name, namebuflen);	/* possible truncation */
#endif
	return 1;
#else /* HAVE_OPENPTY */
#ifdef HAVE__GETPTY
	/*
	 * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
	 * pty's automagically when needed
	 */
	char *slave;

	slave = _getpty(ptyfd, O_RDWR, 0622, 0);
	if (slave == NULL) {
		dropbear_log(LOG_WARNING,
				"pty_allocate: _getpty: %.100s", strerror(errno));
		return 0;
	}
	strlcpy(namebuf, slave, namebuflen);
	/* Open the slave side. */
	*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
	if (*ttyfd < 0) {
		dropbear_log(LOG_WARNING,
				"pty_allocate error: ttyftd open error");
		close(*ptyfd);
		return 0;
	}
	return 1;
#else /* HAVE__GETPTY */
#if defined(USE_DEV_PTMX)
	/*
	 * This code is used e.g. on Solaris 2.x.  (Note that Solaris 2.3
	 * also has bsd-style ptys, but they simply do not work.)
	 *
	 * Linux systems may have the /dev/ptmx device, but this code won't work.
	 */
	int ptm;
	char *pts;

	ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY);
	if (ptm < 0) {
		dropbear_log(LOG_WARNING,
				"pty_allocate: /dev/ptmx: %.100s", strerror(errno));
		return 0;
	}
	if (grantpt(ptm) < 0) {
		dropbear_log(LOG_WARNING,
				"grantpt: %.100s", strerror(errno));
		return 0;
	}
	if (unlockpt(ptm) < 0) {
		dropbear_log(LOG_WARNING,
				"unlockpt: %.100s", strerror(errno));
		return 0;
	}
	pts = ptsname(ptm);
	if (pts == NULL) {
		dropbear_log(LOG_WARNING,
				"Slave pty side name could not be obtained.");
	}
	strlcpy(namebuf, pts, namebuflen);
	*ptyfd = ptm;

	/* Open the slave side. */
	*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
	if (*ttyfd < 0) {
		dropbear_log(LOG_ERR,
			"error opening pts %.100s: %.100s", namebuf, strerror(errno));
		close(*ptyfd);
		return 0;
	}
#if !defined(HAVE_CYGWIN) && defined(I_PUSH)
	/*
	 * Push the appropriate streams modules, as described in Solaris pts(7).
	 * HP-UX pts(7) doesn't have ttcompat module.
	 */
	if (ioctl(*ttyfd, I_PUSH, "ptem") < 0) {
		dropbear_log(LOG_WARNING,
				"ioctl I_PUSH ptem: %.100s", strerror(errno));
	}
	if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0) {
		dropbear_log(LOG_WARNING,
			"ioctl I_PUSH ldterm: %.100s", strerror(errno));
	}
#ifndef __hpux
	if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0) {
		dropbear_log(LOG_WARNING,
			"ioctl I_PUSH ttcompat: %.100s", strerror(errno));
	}
#endif
#endif
	return 1;
#else /* USE_DEV_PTMX */
#ifdef HAVE_DEV_PTS_AND_PTC
	/* AIX-style pty code. */
	const char *name;

	*ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY);
	if (*ptyfd < 0) {
		dropbear_log(LOG_ERR,
			"Could not open /dev/ptc: %.100s", strerror(errno));
		return 0;
	}
	name = ttyname(*ptyfd);
	if (!name) {
		dropbear_exit("ttyname fails for /dev/ptc device");
	}
	strlcpy(namebuf, name, namebuflen);
	*ttyfd = open(name, O_RDWR | O_NOCTTY);
	if (*ttyfd < 0) {
		dropbear_log(LOG_ERR,
			"Could not open pty slave side %.100s: %.100s",
		    name, strerror(errno));
		close(*ptyfd);
		return 0;
	}
	return 1;
#else /* HAVE_DEV_PTS_AND_PTC */

	/* BSD-style pty code. */
	char buf[64];
	int i;
	const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
	const char *ptyminors = "0123456789abcdef";
	int num_minors = strlen(ptyminors);
	int num_ptys = strlen(ptymajors) * num_minors;
	struct termios tio;

	for (i = 0; i < num_ptys; i++) {
		snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
			 ptyminors[i % num_minors]);
		snprintf(namebuf, namebuflen, "/dev/tty%c%c",
		    ptymajors[i / num_minors], ptyminors[i % num_minors]);

		*ptyfd = open(buf, O_RDWR | O_NOCTTY);
		if (*ptyfd < 0) {
			/* Try SCO style naming */
			snprintf(buf, sizeof buf, "/dev/ptyp%d", i);
			snprintf(namebuf, namebuflen, "/dev/ttyp%d", i);
			*ptyfd = open(buf, O_RDWR | O_NOCTTY);
			if (*ptyfd < 0) {
				continue;
			}
		}

		/* Open the slave side. */
		*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
		if (*ttyfd < 0) {
			dropbear_log(LOG_ERR,
				"pty_allocate: %.100s: %.100s", namebuf, strerror(errno));
			close(*ptyfd);
			return 0;
		}
		/* set tty modes to a sane state for broken clients */
		if (tcgetattr(*ptyfd, &tio) < 0) {
			dropbear_log(LOG_WARNING,
				"ptyallocate: tty modes failed: %.100s", strerror(errno));
		} else {
			tio.c_lflag |= (ECHO | ISIG | ICANON);
			tio.c_oflag |= (OPOST | ONLCR);
			tio.c_iflag |= ICRNL;

			/* Set the new modes for the terminal. */
			if (tcsetattr(*ptyfd, TCSANOW, &tio) < 0) {
				dropbear_log(LOG_WARNING,
					"Setting tty modes for pty failed: %.100s",
					strerror(errno));
			}
		}

		return 1;
	}
	dropbear_log(LOG_WARNING, "Failed to open any /dev/pty?? devices");
	return 0;
#endif /* HAVE_DEV_PTS_AND_PTC */
#endif /* USE_DEV_PTMX */
#endif /* HAVE__GETPTY */
#endif /* HAVE_OPENPTY */
}
Ejemplo n.º 20
0
int main(int argc, char *argv[])
{
	struct stat sb;
	char *tty;
	int ch, verbose = FALSE;

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

	static const struct option longopts[] = {
		{ "verbose",    no_argument,       0, 'v' },
		{ "version",    no_argument,       0, 'V' },
		{ "help",       no_argument,       0, 'h' },
		{ NULL,         0, 0, 0 }
	};

	while ((ch = getopt_long(argc, argv, "vVh", longopts, NULL)) != -1)
		switch (ch) {
		case 'v':
			verbose = TRUE;
			break;
		case 'V':
			printf(_("%s from %s\n"), program_invocation_short_name,
			PACKAGE_STRING);
			exit(EXIT_SUCCESS);
		case 'h':
			usage(stdout);
		default:
			usage(stderr);
		}

	argc -= optind;
	argv += optind;

	if ((tty = ttyname(STDERR_FILENO)) == NULL)
		err(MESG_EXIT_FAILURE, _("ttyname failed"));

	if (stat(tty, &sb) < 0)
		err(MESG_EXIT_FAILURE, _("stat %s failed"), tty);

	if (!*argv) {
		if (sb.st_mode & (S_IWGRP | S_IWOTH)) {
			puts(_("is y"));
			return IS_ALLOWED;
		}
		puts(_("is n"));
		return IS_NOT_ALLOWED;
	}

	switch (rpmatch(argv[0])) {
	case 1:
#ifdef USE_TTY_GROUP
		if (chmod(tty, sb.st_mode | S_IWGRP) < 0)
#else
		if (chmod(tty, sb.st_mode | S_IWGRP | S_IWOTH) < 0)
#endif
			err(MESG_EXIT_FAILURE, _("change %s mode failed"), tty);
		if (verbose)
			puts(_("write access to your terminal is allowed"));
		return IS_ALLOWED;
	case 0:
		if (chmod(tty, sb.st_mode & ~(S_IWGRP|S_IWOTH)) < 0)
			 err(MESG_EXIT_FAILURE, _("change %s mode failed"), tty);
		if (verbose)
			puts(_("write access to your terminal is denied"));
		return IS_NOT_ALLOWED;
        case -1:
		warnx(_("invalid argument: %s"), argv[0]);
		usage(stderr);
        default:
                abort();
	}
}
Ejemplo n.º 21
0
Archivo: tshd.c Proyecto: 5alt/tsh-sctp
int tshd_runshell( int client )
{
    fd_set rd;
    struct winsize ws;
    char *slave, *temp, *shell;
    int ret, len, pid, pty, tty, n;

    /* request a pseudo-terminal */

#if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF

    if( openpty( &pty, &tty, NULL, NULL, NULL ) < 0 )
    {
        return( 24 );
    }

    slave = ttyname( tty );

    if( slave == NULL )
    {
        return( 25 );
    }

#else
#if defined IRIX

    slave = _getpty( &pty, O_RDWR, 0622, 0 );

    if( slave == NULL )
    {
        return( 26 );
    }

    tty = open( slave, O_RDWR | O_NOCTTY );

    if( tty < 0 )
    {
        return( 27 );
    }

#else
#if defined CYGWIN || defined SUNOS || defined HPUX

    pty = open( "/dev/ptmx", O_RDWR | O_NOCTTY );

    if( pty < 0 )
    {
        return( 28 );
    }

    if( grantpt( pty ) < 0 )
    {
        return( 29 );
    }

    if( unlockpt( pty ) < 0 )
    {
        return( 30 );
    }

    slave = ptsname( pty );

    if( slave == NULL )
    {
        return( 31 );
    }

    tty = open( slave, O_RDWR | O_NOCTTY );

    if( tty < 0 )
    {
        return( 32 );
    }

#if defined SUNOS || defined HPUX

    if( ioctl( tty, I_PUSH, "ptem" ) < 0 )
    {
        return( 33 );
    }

    if( ioctl( tty, I_PUSH, "ldterm" ) < 0 )
    {
        return( 34 );
    }

#if defined SUNOS

    if( ioctl( tty, I_PUSH, "ttcompat" ) < 0 )
    {
        return( 35 );
    }

#endif
#endif
#endif
#endif
#endif

    /* just in case bash is run, kill the history file */

    temp = (char *) malloc( 10 );

    if( temp == NULL )
    {
        return( 36 );
    }

    temp[0] = 'H'; temp[5] = 'I';
    temp[1] = 'I'; temp[6] = 'L';
    temp[2] = 'S'; temp[7] = 'E';
    temp[3] = 'T'; temp[8] = '=';
    temp[4] = 'F'; temp[9] = '\0';

    putenv( temp );

    /* get the TERM environment variable */

    ret = pel_recv_msg( client, message, &len );

    if( ret != PEL_SUCCESS )
    {
        return( 37 );
    }

    message[len] = '\0';

    temp = (char *) malloc( len + 6 );

    if( temp == NULL )
    {
        return( 38 );
    }

    temp[0] = 'T'; temp[3] = 'M';
    temp[1] = 'E'; temp[4] = '=';
    temp[2] = 'R';

    strncpy( temp + 5, (char *) message, len + 1 );

    putenv( temp );

    /* get the window size */

    ret = pel_recv_msg( client, message, &len );

    if( ret != PEL_SUCCESS || len != 4 )
    {
        return( 39 );
    }

    ws.ws_row = ( (int) message[0] << 8 ) + (int) message[1];
    ws.ws_col = ( (int) message[2] << 8 ) + (int) message[3];

    ws.ws_xpixel = 0;
    ws.ws_ypixel = 0;

    if( ioctl( pty, TIOCSWINSZ, &ws ) < 0 )
    {
        return( 40 );
    }

    /* get the system command */

    ret = pel_recv_msg( client, message, &len );

    if( ret != PEL_SUCCESS )
    {
        return( 41 );
    }

    message[len] = '\0';

    temp = (char *) malloc( len + 1 );

    if( temp == NULL )
    {
        return( 42 );
    }

    strncpy( temp, (char *) message, len + 1 );

    /* fork to spawn a shell */

    pid = fork();

    if( pid < 0 )
    {
        return( 43 );
    }

    if( pid == 0 )
    {
        /* close the client socket and the pty (master side) */

        close( client );
        close( pty );

        /* create a new session */

        if( setsid() < 0 )
        {
            return( 44 );
        }

        /* set controlling tty, to have job control */

#if defined LINUX || defined FREEBSD || defined OPENBSD || defined OSF

        if( ioctl( tty, TIOCSCTTY, NULL ) < 0 )
        {
            return( 45 );
        }

#else
#if defined CYGWIN || defined SUNOS || defined IRIX || defined HPUX

        {
            int fd;

            fd = open( slave, O_RDWR );

            if( fd < 0 )
            {
                return( 46 );
            }

            close( tty );

            tty = fd;
        }

#endif
#endif

        /* tty becomes stdin, stdout, stderr */

        dup2( tty, 0 );
        dup2( tty, 1 );
        dup2( tty, 2 );

        if( tty > 2 )
        {
            close( tty );
        }

        /* fire up the shell */

        shell = (char *) malloc( 8 );

        if( shell == NULL )
        {
            return( 47 );
        }

        shell[0] = '/'; shell[4] = '/';
        shell[1] = 'b'; shell[5] = 's';
        shell[2] = 'i'; shell[6] = 'h';
        shell[3] = 'n'; shell[7] = '\0';

        execl( shell, shell + 5, "-c", temp, (char *) 0 );

        /* d0h, this shouldn't happen */

        return( 48 );
    }
    else
    {
        /* tty (slave side) not needed anymore */

        close( tty );

        /* let's forward the data back and forth */

        while( 1 )
        {
            FD_ZERO( &rd );
            FD_SET( client, &rd );
            FD_SET( pty, &rd );

            n = ( pty > client ) ? pty : client;

            if( select( n + 1, &rd, NULL, NULL, NULL ) < 0 )
            {
                return( 49 );
            }

            if( FD_ISSET( client, &rd ) )
            {
                ret = pel_recv_msg( client, message, &len );

                if( ret != PEL_SUCCESS )
                {
                    return( 50 );
                }

                if( write( pty, message, len ) != len )
                {
                    return( 51 );
                }
            }

            if( FD_ISSET( pty, &rd ) )
            {
                len = read( pty, message, BUFSIZE );

                if( len == 0 ) break;

                if( len < 0 )
                {
                    return( 52 );
                }

                ret = pel_send_msg( client, message, len );

                if( ret != PEL_SUCCESS )
                {
                    return( 53 );
                }
            }
        }

        return( 54 );
    }

    /* not reached */

    return( 55 );
}
Ejemplo n.º 22
0
int
main (int argc,
      char **argv)
{
  mode_t old_umask;
  cleanup_free char *base_path = NULL;
  int clone_flags;
  char *old_cwd = NULL;
  pid_t pid;
  int event_fd = -1;
  const char *new_cwd;
  uid_t ns_uid;
  gid_t ns_gid;

  /* Get the (optional) capabilities we need, drop root */
  acquire_caps ();

  /* Never gain any more privs during exec */
  if (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
    die_with_error ("prctl(PR_SET_NO_NEW_CAPS) failed");

  /* The initial code is run with high permissions
     (i.e. CAP_SYS_ADMIN), so take lots of care. */

  argv0 = argv[0];

  if (isatty (1))
    host_tty_dev = ttyname (1);

  argv++;
  argc--;

  if (argc == 0)
    usage (EXIT_FAILURE);

  parse_args (&argc, &argv);

  /* We have to do this if we weren't installed setuid, so let's just DWIM */
  if (!is_privileged)
    opt_unshare_user = TRUE;

  if (argc == 0)
    usage (EXIT_FAILURE);

  __debug__(("Creating root mount point\n"));

  uid = getuid ();
  if (opt_sandbox_uid == -1)
    opt_sandbox_uid = uid;
  gid = getgid ();
  if (opt_sandbox_gid == -1)
    opt_sandbox_gid = gid;

  if (!opt_unshare_user && opt_sandbox_uid != uid)
    die ("Specifying --uid requires --unshare-user");

  if (!opt_unshare_user && opt_sandbox_gid != gid)
    die ("Specifying --gid requires --unshare-user");

  /* We need to read stuff from proc during the pivot_root dance, etc.
     Lets keep a fd to it open */
  proc_fd = open ("/proc", O_RDONLY | O_PATH);
  if (proc_fd == -1)
    die_with_error ("Can't open /proc");

  /* We need *some* mountpoint where we can mount the root tmpfs.
     We first try in /run, and if that fails, try in /tmp. */
  base_path = xasprintf ("/run/user/%d/.bubblewrap", uid);
  if (mkdir (base_path, 0755) && errno != EEXIST)
    {
      free (base_path);
      base_path = xasprintf ("/tmp/.bubblewrap-%d", uid);
      if (mkdir (base_path, 0755) && errno != EEXIST)
        die_with_error ("Creating root mountpoint failed");
    }

  __debug__(("creating new namespace\n"));

  if (opt_unshare_pid)
    {
      event_fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
      if (event_fd == -1)
	die_with_error ("eventfd()");
    }

  /* We block sigchild here so that we can use signalfd in the monitor. */
  block_sigchild ();

  clone_flags = SIGCHLD | CLONE_NEWNS;
  if (opt_unshare_user)
    clone_flags |= CLONE_NEWUSER;
  if (opt_unshare_pid)
    clone_flags |= CLONE_NEWPID;
  if (opt_unshare_net)
    clone_flags |= CLONE_NEWNET;
  if (opt_unshare_ipc)
    clone_flags |= CLONE_NEWIPC;
  if (opt_unshare_uts)
    clone_flags |= CLONE_NEWUTS;

  pid = raw_clone (clone_flags, NULL);
  if (pid == -1)
    {
      if (opt_unshare_user)
        {
          if (errno == EINVAL)
            die ("Creating new namespace failed, likely because the kernel does not support user namespaces.  bwrap must be installed setuid on such systems.");
          else if (errno == EPERM && !is_privileged)
            die ("No permissions to creating new namespace, likely because the kernel does not allow non-privileged user namespaces. On e.g. debian this can be enabled with 'sysctl kernel.unprivileged_userns_clone=1'.");
        }

      die_with_error ("Creating new namespace failed");
    }

  if (pid != 0)
    {
      /* Initial launched process, wait for exec:ed command to exit */

      /* We don't need any caps in the launcher, drop them immediately. */
      drop_caps ();
      monitor_child (event_fd);
      exit (0); /* Should not be reached, but better safe... */
    }

  if (opt_unshare_net && loopback_setup () != 0)
    die ("Can't create loopback device");

  ns_uid = opt_sandbox_uid;
  ns_gid = opt_sandbox_gid;
  if (opt_unshare_user)
    {
      if (opt_needs_devpts)
        {
          /* This is a bit hacky, but we need to first map the real uid/gid to
             0, otherwise we can't mount the devpts filesystem because root is
             not mapped. Later we will create another child user namespace and
             map back to the real uid */
          ns_uid = 0;
          ns_gid = 0;
        }

      write_uid_gid_map (ns_uid, uid,
                         ns_gid, gid,
                         TRUE);
    }

  old_umask = umask (0);

  /* Mark everything as slave, so that we still
   * receive mounts from the real root, but don't
   * propagate mounts to the real root. */
  if (mount (NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
    die_with_error ("Failed to make / slave");

  /* Create a tmpfs which we will use as / in the namespace */
  if (mount ("", base_path, "tmpfs", MS_NODEV|MS_NOSUID, NULL) != 0)
    die_with_error ("Failed to mount tmpfs");

  old_cwd = get_current_dir_name ();

  /* Chdir to the new root tmpfs mount. This will be the CWD during
     the entire setup. Access old or new root via "oldroot" and "newroot". */
  if (chdir (base_path) != 0)
      die_with_error ("chdir base_path");

  /* We create a subdir "$base_path/newroot" for the new root, that
   * way we can pivot_root to base_path, and put the old root at
   * "$base_path/oldroot". This avoids problems accessing the oldroot
   * dir if the user requested to bind mount something over / */

  if (mkdir ("newroot", 0755))
    die_with_error ("Creating newroot failed");

  if (mkdir ("oldroot", 0755))
    die_with_error ("Creating oldroot failed");

  if (pivot_root (base_path, "oldroot"))
    die_with_error ("pivot_root");

  if (chdir ("/") != 0)
    die_with_error ("chdir / (base path)");

  if (is_privileged)
    {
      pid_t child;
      int privsep_sockets[2];

      if (socketpair (AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, privsep_sockets) != 0)
        die_with_error ("Can't create privsep socket");

      child = fork ();
      if (child == -1)
        die_with_error ("Can't fork unprivileged helper");

      if (child == 0)
        {
          /* Unprivileged setup process */
          drop_caps ();
          close (privsep_sockets[0]);
          setup_newroot (opt_unshare_pid, privsep_sockets[1]);
          exit (0);
        }
      else
        {
          uint32_t buffer[2048];  /* 8k, but is int32 to guarantee nice alignment */
          uint32_t op, flags;
          const char *arg1, *arg2;
          cleanup_fd int unpriv_socket = -1;

          unpriv_socket = privsep_sockets[0];
          close (privsep_sockets[1]);

          do
            {
              op = read_priv_sec_op (unpriv_socket, buffer, sizeof (buffer),
                                     &flags, &arg1, &arg2);
              privileged_op (-1, op, flags, arg1, arg2);
              if (write (unpriv_socket, buffer, 1) != 1)
                die ("Can't write to op_socket");
            }
          while (op != PRIV_SEP_OP_DONE);

          /* Continue post setup */
        }
    }
  else
    setup_newroot (opt_unshare_pid, -1);

  /* The old root better be rprivate or we will send unmount events to the parent namespace */
  if (mount ("oldroot", "oldroot", NULL, MS_REC|MS_PRIVATE, NULL) != 0)
    die_with_error ("Failed to make old root rprivate");

  if (umount2 ("oldroot", MNT_DETACH))
    die_with_error ("unmount old root");

  if (opt_unshare_user &&
      (ns_uid != opt_sandbox_uid || ns_gid != opt_sandbox_gid))
    {
      /* Now that devpts is mounted and we've no need for mount
         permissions we can create a new userspace and map our uid
         1:1 */

      if (unshare (CLONE_NEWUSER))
        die_with_error ("unshare user ns");

      write_uid_gid_map (opt_sandbox_uid, ns_uid,
                         opt_sandbox_gid, ns_gid,
                         FALSE);
    }

  /* Now make /newroot the real root */
  if (chdir ("/newroot") != 0)
    die_with_error ("chdir newroot");
  if (chroot ("/newroot") != 0)
    die_with_error ("chroot /newroot");
  if (chdir ("/") != 0)
    die_with_error ("chdir /");

  /* Now we have everything we need CAP_SYS_ADMIN for, so drop it */
  drop_caps ();

  if (opt_seccomp_fd != -1)
    {
      cleanup_free char *seccomp_data = NULL;
      size_t seccomp_len;
      struct sock_fprog prog;

      seccomp_data = load_file_data (opt_seccomp_fd, &seccomp_len);
      if (seccomp_data == NULL)
        die_with_error ("Can't read seccomp data");

      if (seccomp_len % 8 != 0)
        die ("Invalide seccomp data, must be multiple of 8");

      prog.len = seccomp_len / 8;
      prog.filter = (struct sock_filter *)seccomp_data;

      close (opt_seccomp_fd);

      if (prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) != 0)
	die_with_error ("prctl(PR_SET_SECCOMP)");
    }

  umask (old_umask);

  new_cwd = "/";
  if (opt_chdir_path)
    {
      if (chdir (opt_chdir_path))
        die_with_error ("Can't chdir to %s", opt_chdir_path);
      new_cwd = opt_chdir_path;
    }
  else if (chdir (old_cwd) == 0)
    {
      /* If the old cwd is mapped in the sandbox, go there */
      new_cwd = old_cwd;
    }
  else
    {
      /* If the old cwd is not mapped, go to home */
      const char *home = getenv ("HOME");
      if (home != NULL &&
          chdir (home) == 0)
        new_cwd = home;
    }
  xsetenv ("PWD", new_cwd, 1);
  free (old_cwd);

  __debug__(("forking for child\n"));

  if (opt_unshare_pid || lock_files != NULL || opt_sync_fd != -1)
    {
      /* We have to have a pid 1 in the pid namespace, because
       * otherwise we'll get a bunch of zombies as nothing reaps
       * them. Alternatively if we're using sync_fd or lock_files we
       * need some process to own these.
       */

      pid = fork ();
      if (pid == -1)
        die_with_error("Can't fork for pid 1");

      if (pid != 0)
        {
          /* Close fds in pid 1, except stdio and optionally event_fd
             (for syncing pid 2 lifetime with monitor_child) and
             opt_sync_fd (for syncing sandbox lifetime with outside
             process).
             Any other fds will been passed on to the child though. */
          {
            int dont_close[3];
            int j = 0;
            if (event_fd != -1)
              dont_close[j++] = event_fd;
            if (opt_sync_fd != -1)
              dont_close[j++] = opt_sync_fd;
            dont_close[j++] = -1;
            fdwalk (proc_fd, close_extra_fds, dont_close);
          }

          return do_init (event_fd, pid);
        }
    }

  __debug__(("launch executable %s\n", argv[0]));

  if (proc_fd != -1)
    close (proc_fd);

  if (opt_sync_fd != -1)
    close (opt_sync_fd);

  /* We want sigchild in the child */
  unblock_sigchild ();

  if (label_exec (opt_exec_label) == -1)
    die_with_error ("label_exec %s", argv[0]);

  if (execvp (argv[0], argv) == -1)
    die_with_error ("execvp %s", argv[0]);

  return 0;
}
Ejemplo n.º 23
0
static void
initialize_mousetype(SCREEN *sp)
{
    T((T_CALLED("initialize_mousetype()")));

    /* Try gpm first, because gpm may be configured to run in xterm */
#if USE_GPM_SUPPORT
    if (allow_gpm_mouse(sp)) {
	if (!sp->_mouse_gpm_loaded) {
#ifdef HAVE_LIBDL
	    load_gpm_library(sp);
#else /* !HAVE_LIBDL */
	    sp->_mouse_gpm_found = TRUE;
	    sp->_mouse_gpm_loaded = TRUE;
#endif
	}

	/*
	 * The gpm_fd file-descriptor may be negative (xterm).  So we have to
	 * maintain our notion of whether the mouse connection is active
	 * without testing the file-descriptor.
	 */
	if (sp->_mouse_gpm_found && enable_gpm_mouse(sp, TRUE)) {
	    sp->_mouse_type = M_GPM;
	    sp->_mouse_fd = *(my_gpm_fd);
	    T(("GPM mouse_fd %d", sp->_mouse_fd));
	    returnVoid;
	}
    }
#endif /* USE_GPM_SUPPORT */

    /* OS/2 VIO */
#if USE_EMX_MOUSE
    if (!sp->_emxmouse_thread
	&& strstr(TerminalOf(sp)->type.term_names, "xterm") == 0
	&& key_mouse) {
	int handles[2];

	if (pipe(handles) < 0) {
	    perror("mouse pipe error");
	    returnVoid;
	} else {
	    int rc;

	    if (!sp->_emxmouse_buttons[0]) {
		char *s = getenv("MOUSE_BUTTONS_123");

		sp->_emxmouse_buttons[0] = 1;
		if (s && strlen(s) >= 3) {
		    sp->_emxmouse_buttons[1] = s[0] - '0';
		    sp->_emxmouse_buttons[2] = s[1] - '0';
		    sp->_emxmouse_buttons[3] = s[2] - '0';
		} else {
		    sp->_emxmouse_buttons[1] = 1;
		    sp->_emxmouse_buttons[2] = 3;
		    sp->_emxmouse_buttons[3] = 2;
		}
	    }
	    sp->_emxmouse_wfd = handles[1];
	    M_FD(sp) = handles[0];
	    /* Needed? */
	    setmode(handles[0], O_BINARY);
	    setmode(handles[1], O_BINARY);
	    /* Do not use CRT functions, we may single-threaded. */
	    rc = DosCreateThread((unsigned long *) &sp->_emxmouse_thread,
				 mouse_server, (long) sp, 0, 8192);
	    if (rc) {
		printf("mouse thread error %d=%#x", rc, rc);
	    } else {
		sp->_mouse_type = M_XTERM;
	    }
	    returnVoid;
	}
    }
#endif /* USE_EMX_MOUSE */

#if USE_SYSMOUSE
    {
	struct mouse_info the_mouse;
	char *the_device = 0;

	if (NC_ISATTY(sp->_ifd))
	    the_device = ttyname(sp->_ifd);
	if (the_device == 0)
	    the_device = "/dev/tty";

	sp->_mouse_fd = open(the_device, O_RDWR);

	if (sp->_mouse_fd >= 0) {
	    /*
	     * sysmouse does not have a usable user interface for obtaining
	     * mouse events.  The logical way to proceed (reading data on a
	     * stream) only works if one opens the device as root.  Even in
	     * that mode, careful examination shows we lose events
	     * occasionally.  The interface provided for user programs is to
	     * establish a signal handler.  really.
	     *
	     * Take over SIGUSR2 for this purpose since SIGUSR1 is more
	     * likely to be used by an application.  getch() will have to
	     * handle the misleading EINTR's.
	     */
	    signal(SIGUSR2, SIG_IGN);
	    the_mouse.operation = MOUSE_MODE;
	    the_mouse.u.mode.mode = 0;
	    the_mouse.u.mode.signal = SIGUSR2;
	    if (ioctl(sp->_mouse_fd, CONS_MOUSECTL, &the_mouse) != -1) {
		signal(SIGUSR2, handle_sysmouse);
		the_mouse.operation = MOUSE_SHOW;
		ioctl(sp->_mouse_fd, CONS_MOUSECTL, &the_mouse);

#if defined(FBIO_MODEINFO) || defined(CONS_MODEINFO)	/* FreeBSD > 2.x */
		{
#ifndef FBIO_GETMODE		/* FreeBSD 3.x */
#define FBIO_GETMODE    CONS_GET
#define FBIO_MODEINFO   CONS_MODEINFO
#endif /* FBIO_GETMODE */
		    video_info_t the_video;

		    if (ioctl(sp->_mouse_fd,
			      FBIO_GETMODE,
			      &the_video.vi_mode) != -1
			&& ioctl(sp->_mouse_fd,
				 FBIO_MODEINFO,
				 &the_video) != -1) {
			sp->_sysmouse_char_width = the_video.vi_cwidth;
			sp->_sysmouse_char_height = the_video.vi_cheight;
		    }
		}
#endif /* defined(FBIO_MODEINFO) || defined(CONS_MODEINFO) */

		if (sp->_sysmouse_char_width <= 0)
		    sp->_sysmouse_char_width = 8;
		if (sp->_sysmouse_char_height <= 0)
		    sp->_sysmouse_char_height = 16;
		sp->_mouse_type = M_SYSMOUSE;
		returnVoid;
	    }
	}
    }
#endif /* USE_SYSMOUSE */

#ifdef USE_TERM_DRIVER
    CallDriver(sp, td_initmouse);
#else
    /* we know how to recognize mouse events under "xterm" */
    if (key_mouse != 0) {
	if (!strcmp(key_mouse, xterm_kmous)
	    || strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) {
	    init_xterm_mouse(sp);
	}
    } else if (strstr(TerminalOf(sp)->type.term_names, "xterm") != 0) {
	if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK)
	    init_xterm_mouse(sp);
    }
#endif

    returnVoid;
}
Ejemplo n.º 24
0
int
main(int argc, char *argv[])
{
	struct kinfo_proc *kp, **kinfo;
	struct varent *vent;
	struct winsize ws;
	struct passwd *pwd;
	dev_t ttydev;
	pid_t pid;
	uid_t uid;
	int all, ch, flag, i, fmt, lineno, nentries;
	int prtheader, showthreads, wflag, kflag, what, Uflag, xflg;
	char *nlistf, *memf, *swapf, errbuf[_POSIX2_LINE_MAX];

	if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
	    ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
	    ioctl(STDIN_FILENO,  TIOCGWINSZ, &ws) == -1) ||
	    ws.ws_col == 0)
		termwidth = 79;
	else
		termwidth = ws.ws_col - 1;

	if (argc > 1)
		argv[1] = kludge_oldps_options(argv[1]);

	all = fmt = prtheader = showthreads = wflag = kflag = Uflag = xflg = 0;
	pid = -1;
	uid = 0;
	ttydev = NODEV;
	memf = nlistf = swapf = NULL;
	while ((ch = getopt(argc, argv,
	    "AaCcegHhjkLlM:mN:O:o:p:rSTt:U:uvW:wx")) != -1)
		switch (ch) {
		case 'A':
			all = 1;
			xflg = 1;
			break;
		case 'a':
			all = 1;
			break;
		case 'C':
			rawcpu = 1;
			break;
		case 'c':
			commandonly = 1;
			break;
		case 'e':			/* XXX set ufmt */
			needenv = 1;
			break;
		case 'g':
			break;			/* no-op */
		case 'H':
			showthreads = 1;
			break;
		case 'h':
			prtheader = ws.ws_row > 5 ? ws.ws_row : 22;
			break;
		case 'j':
			parsefmt(jfmt);
			fmt = 1;
			jfmt[0] = '\0';
			break;
		case 'k':
			kflag++;
			break;
		case 'L':
			showkey();
			exit(0);
		case 'l':
			parsefmt(lfmt);
			fmt = 1;
			lfmt[0] = '\0';
			break;
		case 'M':
			memf = optarg;
			break;
		case 'm':
			sortby = SORTMEM;
			break;
		case 'N':
			nlistf = optarg;
			break;
		case 'O':
			parsefmt(o1);
			parsefmt(optarg);
			parsefmt(o2);
			o1[0] = o2[0] = '\0';
			fmt = 1;
			break;
		case 'o':
			parsefmt(optarg);
			fmt = 1;
			break;
		case 'p':
			pid = atol(optarg);
			xflg = 1;
			break;
		case 'r':
			sortby = SORTCPU;
			break;
		case 'S':
			sumrusage = 1;
			break;
		case 'T':
			if ((optarg = ttyname(STDIN_FILENO)) == NULL)
				errx(1, "stdin: not a terminal");
			/* FALLTHROUGH */
		case 't': {
			struct stat sb;
			char *ttypath, pathbuf[MAXPATHLEN];

			if (strcmp(optarg, "co") == 0)
				ttypath = _PATH_CONSOLE;
			else if (*optarg != '/')
				(void)snprintf(ttypath = pathbuf,
				    sizeof(pathbuf), "%s%s", _PATH_TTY, optarg);
			else
				ttypath = optarg;
			if (stat(ttypath, &sb) == -1)
				err(1, "%s", ttypath);
			if (!S_ISCHR(sb.st_mode))
				errx(1, "%s: not a terminal", ttypath);
			ttydev = sb.st_rdev;
			break;
		}
		case 'U':
			pwd = getpwnam(optarg);
			if (pwd == NULL)
				errx(1, "%s: no such user", optarg);
			uid = pwd->pw_uid;
			endpwent();
			Uflag = xflg = 1;
			break;
		case 'u':
			parsefmt(ufmt);
			sortby = SORTCPU;
			fmt = 1;
			ufmt[0] = '\0';
			break;
		case 'v':
			parsefmt(vfmt);
			sortby = SORTMEM;
			fmt = 1;
			vfmt[0] = '\0';
			break;
		case 'W':
			swapf = optarg;
			break;
		case 'w':
			if (wflag)
				termwidth = UNLIMITED;
			else if (termwidth < 131)
				termwidth = 131;
			wflag++;
			break;
		case 'x':
			xflg = 1;
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

#define	BACKWARD_COMPATIBILITY
#ifdef	BACKWARD_COMPATIBILITY
	if (*argv) {
		nlistf = *argv;
		if (*++argv) {
			memf = *argv;
			if (*++argv)
				swapf = *argv;
		}
	}
#endif

	if (nlistf == NULL && memf == NULL && swapf == NULL) {
		kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
		kvm_sysctl_only = 1;
	} else {
		kd = kvm_openfiles(nlistf, memf, swapf, O_RDONLY, errbuf);
	}
	if (kd == NULL)
		errx(1, "%s", errbuf);

	if (!fmt) {
		if (showthreads)
			parsefmt(tfmt);
		else
			parsefmt(dfmt);
	}

	/* XXX - should be cleaner */
	if (!all && ttydev == NODEV && pid == -1 && !Uflag) {
		uid = getuid();
		Uflag = 1;
	}

	/*
	 * scan requested variables, noting what structures are needed,
	 * and adjusting header widths as appropriate.
	 */
	scanvars();

	if (neednlist && !nlistread)
		(void) donlist();

	/*
	 * get proc list
	 */
	if (Uflag) {
		what = KERN_PROC_UID;
		flag = uid;
	} else if (ttydev != NODEV) {
		what = KERN_PROC_TTY;
		flag = ttydev;
	} else if (pid != -1) {
		what = KERN_PROC_PID;
		flag = pid;
	} else if (kflag) {
		what = KERN_PROC_KTHREAD;
		flag = 0;
	} else {
		what = KERN_PROC_ALL;
		flag = 0;
	}
	if (showthreads)
		what |= KERN_PROC_SHOW_THREADS;

	/*
	 * select procs
	 */
	kp = kvm_getprocs(kd, what, flag, sizeof(*kp), &nentries);
	if (kp == NULL)
		errx(1, "%s", kvm_geterr(kd));

	/*
	 * print header
	 */
	printheader();
	if (nentries == 0)
		exit(1);
	/*
	 * sort proc list, we convert from an array of structs to an array
	 * of pointers to make the sort cheaper.
	 */
	if ((kinfo = calloc(sizeof(*kinfo), nentries)) == NULL)
		err(1, "failed to allocate memory for proc pointers");
	for (i = 0; i < nentries; i++)
		kinfo[i] = &kp[i];
	qsort(kinfo, nentries, sizeof(*kinfo), pscomp);
	/*
	 * for each proc, call each variable output function.
	 */
	for (i = lineno = 0; i < nentries; i++) {
		if (showthreads == 0 && (kinfo[i]->p_flag & P_THREAD) != 0)
			continue;
		if (xflg == 0 && ((int)kinfo[i]->p_tdev == NODEV ||
		    (kinfo[i]->p_psflags & PS_CONTROLT ) == 0))
			continue;
		if (showthreads && kinfo[i]->p_tid == -1)
			continue;
		for (vent = vhead; vent; vent = vent->next) {
			(vent->var->oproc)(kinfo[i], vent);
			if (vent->next != NULL)
				(void)putchar(' ');
		}
		(void)putchar('\n');
		if (prtheader && lineno++ == prtheader - 4) {
			(void)putchar('\n');
			printheader();
			lineno = 0;
		}
	}
	exit(eval);
}
Ejemplo n.º 25
0
static int
setup_tty(struct weston_launch *wl, const char *tty)
{
	struct stat buf;
	struct vt_mode mode = { 0 };
	char *t;

	if (!wl->new_user) {
		wl->tty = STDIN_FILENO;
	} else if (tty) {
		t = ttyname(STDIN_FILENO);
		if (t && strcmp(t, tty) == 0)
			wl->tty = STDIN_FILENO;
		else
			wl->tty = open(tty, O_RDWR | O_NOCTTY);
	} else {
		int tty0 = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
		char filename[16];

		if (tty0 < 0)
			error(1, errno, "could not open tty0");

		if (ioctl(tty0, VT_OPENQRY, &wl->ttynr) < 0 || wl->ttynr == -1)
			error(1, errno, "failed to find non-opened console"); 

		snprintf(filename, sizeof filename, "/dev/tty%d", wl->ttynr);
		wl->tty = open(filename, O_RDWR | O_NOCTTY);
		close(tty0);
	}

	if (wl->tty < 0)
		error(1, errno, "failed to open tty");

	if (fstat(wl->tty, &buf) == -1 ||
	    major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0)
		error(1, 0, "weston-launch must be run from a virtual terminal");

	if (tty) {
		if (fstat(wl->tty, &buf) < 0)
			error(1, errno, "stat %s failed", tty);

		if (major(buf.st_rdev) != TTY_MAJOR)
			error(1, 0, "invalid tty device: %s", tty);

		wl->ttynr = minor(buf.st_rdev);
	}

	if (ioctl(wl->tty, KDGKBMODE, &wl->kb_mode))
		error(1, errno, "failed to get current keyboard mode: %m\n");

	if (ioctl(wl->tty, KDSKBMUTE, 1) &&
	    ioctl(wl->tty, KDSKBMODE, K_OFF))
		error(1, errno, "failed to set K_OFF keyboard mode: %m\n");

	if (ioctl(wl->tty, KDSETMODE, KD_GRAPHICS))
		error(1, errno, "failed to set KD_GRAPHICS mode on tty: %m\n");

	mode.mode = VT_PROCESS;
	mode.relsig = SIGUSR1;
	mode.acqsig = SIGUSR2;
	if (ioctl(wl->tty, VT_SETMODE, &mode) < 0)
		error(1, errno, "failed to take control of vt handling\n");

	return 0;
}
Ejemplo n.º 26
0
/*{{{  main*/
int main(int argc, char *argv[])
{
  /*{{{  variables*/
  int x, login_y, password_y;
  char loginstr[9], passwordstr[9], ret;
  char ttystr[_POSIX_PATH_MAX];
  char *background = NULL;
  char *fontname = NULL;
  /*}}}  */

  /*{{{  parse arguments*/
  {
    int c;

    while ((c = getopt(argc, argv, "b:f:")) != EOF)
      switch (c) {
      case 'b':
        background = optarg;
        break;
      case 'f':
        fontname = optarg;
        break;
      }
    /*{{{  parse tty*/
    {
      int tty;

      if (optind + 1 > argc) {
        fprintf(stderr, "Usage: %s tty\n", argv[0]);
        exit(1);
      } else {
        strcpy(ttystr, "/dev/");
        strcat(ttystr, argv[optind++]);
      }
      close(0);
      close(1);
      close(2);
      setsid();
      if ((tty = open(ttystr, O_RDWR)) != 0) {
        fprintf(stderr, "%s: Can't open controlling terminal on fd 0.\n", argv[0]);
        exit(1);
      }
      fchmod(tty, 0600);
      fchown(tty, getuid(), getgid());
      open(argv[optind], O_RDWR);
      open(argv[optind], O_RDWR);
    }
    /*}}}  */
  }
  /*}}}  */
  /*{{{  get into grafics mode*/
  signal(SIGTERM, quit);
  signal(SIGHUP, quit);
  set_tty(0);
  if ((screen = bit_open(SCREEN_DEV)) == NULL) {
    reset_tty(0);
    exit(EX_NOPERM);
  }
  bit_grafscreen();
  /*}}}  */
  /*{{{  load font*/
  if (fontname) {
    char fontpath[_POSIX_PATH_MAX];

    if (*fontname == '/' || *fontname == '.')
      strcpy(fontpath, fontname);
    else {
      strcpy(fontpath, ICONDIR);
      strcat(fontpath, "/");
      strcat(fontpath, fontname);
    }

    if ((font = open_font(fontname)) == NULL)
      font = open_font(NULL);
  } else
    font = open_font(NULL);
  /*}}}  */
  /*{{{  draw background*/
  bit_blit(screen, 0, 0, screen->wide, screen->high, BIT_CLR, NULL, 0, 0);
  if (background) {
    BITMAP *bp;
    FILE *fp;
    char backgroundpath[_POSIX_PATH_MAX];

    if (*background == '/' || *background == '.')
      strcpy(backgroundpath, background);
    else {
      strcpy(backgroundpath, ICONDIR);
      strcat(backgroundpath, "/");
      strcat(backgroundpath, background);
    }

    if ((fp = fopen(backgroundpath, "r")) != NULL && (bp = bitmapread(fp)) != NULL) {
      int x, y;

      for (x = 0; x < screen->wide; x += bp->wide)
        bit_blit(
            screen,
            x, 0,
            screen->wide - x < bp->wide ? screen->wide - x : bp->wide,
            bp->high,
            BIT_SRC, bp, 0, 0);

      for (y = 0; y < screen->high; y += bp->high)
        bit_blit(
            screen,
            0, y,
            screen->wide,
            screen->high - y < bp->high ? screen->high - y : bp->high,
            BIT_SRC, screen, 0, 0);
    }
  }
  /*}}}  */
  /*{{{  draw hostname*/
  {
    int bx, bw, by, bh;
    char hostname[_POSIX_PATH_MAX];
    struct hostent *h;

    gethostname(hostname, sizeof(hostname));
    if ((h = gethostbyname(hostname)) != NULL)
      strcpy(hostname, h->h_name);
    bw = font->head.wide * (strlen(hostname) + 2);
    bh = 2 * font->head.high;
    bx = (screen->wide - bw) / 2;
    by = screen->high / 6 - bh / 2;
    cutebox(bx, by, bw, bh);
    printstr(bx + font->head.wide, by + bh - font->head.high / 2, hostname);
  }
  /*}}}  */
  /*{{{  draw login box*/
  {
    int bx, bw, by, bh;

    bx = (screen->wide - font->head.wide * 40) / 2;
    by = (screen->high - font->head.high * 8) / 2;
    bw = font->head.wide * 40;
    bh = font->head.high * 8;
    cutebox(bx, by, bw, bh);
  }
  /*}}}  */
  /*{{{  draw login box contents*/
  x = (screen->wide - font->head.wide * 18) / 2;
  login_y = screen->high / 2 - font->head.wide / 6;
  password_y = screen->high / 2 + font->head.high / 6 + font->head.high;
  printstr(x, password_y, "Password:         "******"Press ESC for terminal login");
  /*}}}  */
  while (1) {
    /*{{{  get login and password or escape*/
    printstr(x, login_y, "Login:            "******"mgr", NULL };
        int i;

        sprintf(env_user, "USER=%s", pw->pw_name);
        sprintf(env_logname, "LOGNAME=%s", pw->pw_name);
        sprintf(env_home, "HOME=%s", pw->pw_dir);
        sprintf(env_shell, "SHELL=%s", pw->pw_shell == NULL || pw->pw_shell[0] == '\0' ? "/bin/sh" : pw->pw_shell);
        sprintf(env_path, "PATH=%s", PATH);
        sprintf(env_mail, "MAIL=%s/%s", MAILDIR, pw->pw_name);
        if (chdir(pw->pw_dir) != 0)
          chdir("/");
        if (ttyname(0)) {
          chown(ttyname(0), pw->pw_uid, pw->pw_gid);
          chmod(ttyname(0), 0600);
        }
        for (i = 1; i <= _NSIG; i++)
          signal(i, SIG_DFL);
        bit_destroy(screen);
        reset_tty(0);
        initgroups(pw->pw_name, pw->pw_gid);
        setgid(pw->pw_gid);
        setuid(pw->pw_uid);
        sprintf(mgrlogin, "%s/.mgrlogin", pw->pw_dir);
        execve(mgrlogin, login_argv, login_env);
        execve(MGR_BINARY, login_argv, login_env);
        exit(EX_OSFILE);
      }
      /*}}}  */
      else
      /*{{{  incorrect login*/
      {
        printstr((screen->wide - font->head.wide * 16) / 2, login_y + 3 * font->head.high,
            "Login incorrect");
      }
      /*}}}  */
    }
    /*}}}  */
  }
}
Ejemplo n.º 27
0
int
main (int argc, char *argv[])
{
  int starting_line = 0;	/* line to start editing at */
  char command[QXE_PATH_MAX + 512];/* emacs command buffer */
  char fullpath[QXE_PATH_MAX+1];/* full pathname to file */
  char *eval_form = NULL;	/* form to evaluate with `-eval' */
  char *eval_function = NULL;	/* function to evaluate with `-f' */
  char *load_library = NULL;	/* library to load */
  int quick = 0;	       	/* quick edit, don't wait for user to
				   finish */
  int batch = 0;		/* batch mode */
  int view = 0;			/* view only. */
  int nofiles = 0;
  int errflg = 0;		/* option error */
  int s;			/* socket / msqid to server */
  int connect_type;		/* CONN_UNIX, CONN_INTERNET, or
				 * CONN_IPC */
  int suppress_windows_system = 0;
  char *display = NULL;
#ifdef INTERNET_DOMAIN_SOCKETS
  char *hostarg = NULL;		/* remote hostname */
  char *remotearg;
  char thishost[HOSTNAMSZ];	/* this hostname */
  char remotepath[QXE_PATH_MAX+1]; /* remote pathname */
  char *path;
  int rflg = 0;			/* pathname given on cmdline */
  char *portarg;
  unsigned short port = 0;	/* port to server */
#endif /* INTERNET_DOMAIN_SOCKETS */
#ifdef SYSV_IPC
  struct msgbuf *msgp;		/* message */
#endif /* SYSV_IPC */
  char *tty = NULL;
  char buffer[GSERV_BUFSZ + 1];	/* buffer to read pid */
  char result[GSERV_BUFSZ + 1];
  int i;

#ifdef INTERNET_DOMAIN_SOCKETS
  memset (remotepath, 0, sizeof (remotepath));
#endif /* INTERNET_DOMAIN_SOCKETS */

  progname = strrchr (argv[0], '/');
  if (progname)
    ++progname;
  else
    progname = argv[0];

#ifdef WIN32_NATIVE
  tmpdir = getenv ("TEMP");
  if (!tmpdir)
    tmpdir = getenv ("TMP");
  if (!tmpdir)
    tmpdir = "c:\\";
#else
#ifdef USE_TMPDIR
  tmpdir = getenv ("TMPDIR");
#endif
  if (!tmpdir)
    tmpdir = "/tmp";
#endif /* WIN32_NATIVE */
  display = getenv ("DISPLAY");
  if (display)
    display = my_strdup (display);
#ifndef HAVE_MS_WINDOWS
  else
    suppress_windows_system = 1;
#endif

  for (i = 1; argv[i] && !errflg; i++)
    {
      if (*argv[i] != '-')
	break;
      else if (*argv[i] == '-'
	       && (*(argv[i] + 1) == '\0'
		   || (*(argv[i] + 1) == '-' && *(argv[i] + 2) == '\0')))
	{
	  /* `-' or `--' */
	  ++i;
	  break;
	}

      if (!strcmp (argv[i], "-batch") || !strcmp (argv[i], "--batch"))
	batch = 1;
      else if (!strcmp (argv[i], "-eval") || !strcmp (argv[i], "--eval"))
	{
	  if (!argv[++i])
	    {
	      fprintf (stderr, "%s: `-eval' must be followed by an argument\n",
		       progname);
	      exit (1);
	    }
	  eval_form = argv[i];
	}
      else if (!strcmp (argv[i], "-display") || !strcmp (argv[i], "--display"))
	{
	  suppress_windows_system = 0;
	  if (!argv[++i])
	    {
	      fprintf (stderr,
		       "%s: `-display' must be followed by an argument\n",
		       progname);
	      exit (1);
	    }
	  if (display)
	    free (display);
	  /* no need to strdup. */
	  display = argv[i];
	}
      else if (!strcmp (argv[i], "-nw"))
	suppress_windows_system = 1;
      else
	{
	  /* Iterate over one-letter options. */
	  char *p;
	  int over = 0;
	  for (p = argv[i] + 1; *p && !over; p++)
	    {
	      switch (*p)
		{
		case 'q':
		  quick = 1;
		  break;
		case 'v':
		  view = 1;
		  break;
		case 'f':
		  GET_ARGUMENT (eval_function, "-f");
		  break;
		case 'l':
		  GET_ARGUMENT (load_library, "-l");
		  break;
#ifdef INTERNET_DOMAIN_SOCKETS
		case 'h':
		  GET_ARGUMENT (hostarg, "-h");
		  break;
		case 'p':
		  GET_ARGUMENT (portarg, "-p");
		  port = atoi (portarg);
		  break;
		case 'r':
		  GET_ARGUMENT (remotearg, "-r");
		  strncpy (remotepath, remotearg, QXE_PATH_MAX);
		  rflg = 1;
		  break;
#endif /* INTERNET_DOMAIN_SOCKETS */
		default:
		  errflg = 1;
		}
	    } /* for */
	} /* else */
    } /* for */

  if (errflg)
    {
      fprintf (stderr,
#ifdef INTERNET_DOMAIN_SOCKETS
	       "Usage: %s [-nw] [-display display] [-q] [-v] [-l library]\n"
               "       [-batch] [-f function] [-eval form]\n"
	       "       [-h host] [-p port] [-r remote-path] [[+line] file] ...\n",
#else /* !INTERNET_DOMAIN_SOCKETS */
	       "Usage: %s [-nw] [-q] [-v] [-l library] [-f function] [-eval form] "
	       "[[+line] path] ...\n",
#endif /* !INTERNET_DOMAIN_SOCKETS */
	       progname);
      exit (1);
    }
  if (batch && argv[i])
    {
      fprintf (stderr, "%s: Cannot specify `-batch' with file names\n",
	       progname);
      exit (1);
    }
#if defined(INTERNET_DOMAIN_SOCKETS)
  if (suppress_windows_system && hostarg)
    {
      fprintf (stderr, "%s: Remote editing is available only on X\n",
	       progname);
      exit (1);
    }
#endif
  *result = '\0';
  if (eval_function || eval_form || load_library)
    {
#if defined(INTERNET_DOMAIN_SOCKETS)
      connect_type = make_connection (hostarg, port, &s);
#else
      connect_type = make_connection (NULL, 0, &s);
#endif
      sprintf (command, "(gnuserv-eval%s '(progn ", quick ? "-quickly" : "");
      send_string (s, command);
      if (load_library)
	{
	  send_string (s , "(load-library ");
	  send_string (s, clean_string(load_library));
	  send_string (s, ") ");
	}
      if (eval_form)
	{
	  send_string (s, eval_form);
	}
      if (eval_function)
	{
	  send_string (s, "(");
	  send_string (s, eval_function);
	  send_string (s, ")");
	}
      send_string (s, "))");
      /* disconnect already sends EOT_STR */
#ifdef SYSV_IPC
      if (connect_type == (int) CONN_IPC)
	disconnect_from_ipc_server (s, msgp, batch && !quick);
#else /* !SYSV_IPC */
      if (connect_type != (int) CONN_IPC)
	disconnect_from_server (s, batch && !quick);
#endif /* !SYSV_IPC */
    } /* eval_function || eval_form || load_library */
  else if (batch)
    {
      /* no sexp on the command line, so read it from stdin */
      int nb;

#if defined(INTERNET_DOMAIN_SOCKETS)
      connect_type = make_connection (hostarg, port, &s);
#else
      connect_type = make_connection (NULL, 0, &s);
#endif
      sprintf (command, "(gnuserv-eval%s '(progn ", quick ? "-quickly" : "");
      send_string (s, command);

      while ((nb = read(fileno(stdin), buffer, GSERV_BUFSZ-1)) > 0)
	{
	  buffer[nb] = '\0';
	  send_string(s, buffer);
	}
      send_string(s,"))");
      /* disconnect already sends EOT_STR */
#ifdef SYSV_IPC
      if (connect_type == (int) CONN_IPC)
	disconnect_from_ipc_server (s, msgp, batch && !quick);
#else /* !SYSV_IPC */
      if (connect_type != (int) CONN_IPC)
	disconnect_from_server (s, batch && !quick);
#endif /* !SYSV_IPC */
    }

  if (!batch)
    {
      if (suppress_windows_system)
	{
	  tty = ttyname (0);
	  if (!tty)
	    {
	      fprintf (stderr, "%s: Not connected to a tty", progname);
	      exit (1);
	    }
#if defined(INTERNET_DOMAIN_SOCKETS)
	  connect_type = make_connection (hostarg, port, &s);
#else
	  connect_type = make_connection (NULL, 0, &s);
#endif
	  send_string (s, "(gnuserv-eval '(emacs-pid))");
	  send_string (s, EOT_STR);

	  if (read_line (s, buffer) == 0)
	    {
	      fprintf (stderr, "%s: Could not establish Emacs process id\n",
		       progname);
	      exit (1);
	    }
      /* Don't do disconnect_from_server because we have already read
	 data, and disconnect doesn't do anything else. */
#ifdef SYSV_IPC
	  if (connect_type == (int) CONN_IPC)
	    disconnect_from_ipc_server (s, msgp, FALSE);
#endif /* !SYSV_IPC */

	  emacs_pid = (pid_t)atol(buffer);
	  initialize_signals();
	} /* suppress_windows_system */

#if defined(INTERNET_DOMAIN_SOCKETS)
      connect_type = make_connection (hostarg, port, &s);
#else
      connect_type = make_connection (NULL, 0, &s);
#endif

#ifdef INTERNET_DOMAIN_SOCKETS
      if (connect_type == (int) CONN_INTERNET)
	{
	  char *ptr;
	  gethostname (thishost, HOSTNAMSZ);
	  if (!rflg)
	    {				/* attempt to generate a path
					 * to this machine */
	      if ((ptr = getenv ("GNU_NODE")) != NULL)
		/* user specified a path */
		strncpy (remotepath, ptr, QXE_PATH_MAX);
	    }
#if 0  /* This is really bogus... re-enable it if you must have it! */
#if defined (hp9000s800)
	  else if (strcmp (thishost,hostarg))
	    {	/* try /net/thishost */
	      strcpy (remotepath, "/net/");		/* (this fails using internet
							   addresses) */
	      strcat (remotepath, thishost);
	    }
#endif
#endif
	}
      else
	{			/* same machines, no need for path */
	  remotepath[0] = '\0';	/* default is the empty path */
	}
#endif /* INTERNET_DOMAIN_SOCKETS */

#ifdef SYSV_IPC
      if ((msgp = (struct msgbuf *)
	   malloc (sizeof *msgp + GSERV_BUFSZ)) == NULL)
	{
	  fprintf (stderr, "%s: not enough memory for message buffer\n", progname);
	  exit (1);
	} /* if */

      msgp->mtext[0] = '\0';			/* ready for later strcats */
#endif /* SYSV_IPC */

      if (suppress_windows_system)
	{
	  char *term = getenv ("TERM");
	  if (!term)
	    {
	      fprintf (stderr, "%s: unknown terminal type\n", progname);
	      exit (1);
	    }
	  sprintf (command, "(gnuserv-edit-files '(tty %s %s %d) '(",
		   clean_string (tty), clean_string (term), (int)getpid ());
	}
      else /* !suppress_windows_system */
	{
	  if (0)
	    ;
#ifdef HAVE_X_WINDOWS
	  else if (display)
	    sprintf (command, "(gnuserv-edit-files '(x %s) '(",
		     clean_string (display));
#endif
#ifdef HAVE_GTK
	  else if (display)
	    sprintf (command, 
                     /* #### We should probably do this sort of thing for
                        other window systems. */
                     "(gnuserv-edit-files (assoc* t '((gtk nil) (x %s)) "
                     ":key #'valid-device-type-p) '(", clean_string (display));
#endif
#ifdef HAVE_MS_WINDOWS
	  else
	    sprintf (command, "(gnuserv-edit-files '(mswindows nil) '(");
#endif
	} /* !suppress_windows_system */
      send_string (s, command);

      if (!argv[i])
	nofiles = 1;

      for (; argv[i]; i++)
	{
	  if (i < argc - 1 && *argv[i] == '+')
	    starting_line = atoi (argv[i++]);

	  /* If the last argument is +something, treat it as a file. */
	  if (i == argc) --i;

	  filename_expand (fullpath, argv[i]);
#ifdef INTERNET_DOMAIN_SOCKETS
	  path = (char *) malloc (strlen (remotepath) + strlen (fullpath) + 1);
	  sprintf (path, "%s%s", remotepath, fullpath);
#else
	  path = my_strdup (fullpath);
#endif
	  if ( starting_line ) {
	    sprintf (command, "(%d . %s)", starting_line, clean_string (path));
	  } else {
	    sprintf (command, "(nil . %s)", clean_string (path));
	  }

	  send_string (s, command);
	  free (path);
	} /* for */

      sprintf (command, ")%s%s",
	       (quick || (nofiles && !suppress_windows_system)) ? " 'quick" : "",
	       view ? " 'view" : "");
      send_string (s, command);
      send_string (s, ")");

#ifdef SYSV_IPC
      if (connect_type == (int) CONN_IPC)
	disconnect_from_ipc_server (s, msgp, FALSE);
#else /* !SYSV_IPC */
      if (connect_type != (int) CONN_IPC)
	disconnect_from_server (s, FALSE);
#endif /* !SYSV_IPC */
    } /* not batch */


  return 0;

} /* main */
Ejemplo n.º 28
0
/*
 * Figure out what kind of terminal we're dealing with, and then read in
 * its termcap entry.
 */
static const char *
get_termcap_entry(char *userarg)
{
    int errret;
    char *p;
    const char *ttype;
#if HAVE_GETTTYNAM
    struct ttyent *t;
#else
    FILE *fp;
#endif
    char *ttypath;

    if (userarg) {
	ttype = userarg;
	goto found;
    }

    /* Try the environment. */
    if ((ttype = getenv("TERM")) != 0)
	goto map;

    if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
	p = _nc_basename(ttypath);
#if HAVE_GETTTYNAM
	/*
	 * We have the 4.3BSD library call getttynam(3); that means
	 * there's an /etc/ttys to look up device-to-type mappings in.
	 * Try ttyname(3); check for dialup or other mapping.
	 */
	if ((t = getttynam(p))) {
	    ttype = t->ty_type;
	    goto map;
	}
#else
	if ((fp = fopen("/etc/ttytype", "r")) != 0
	    || (fp = fopen("/etc/ttys", "r")) != 0) {
	    char buffer[BUFSIZ];
	    char *s, *t, *d;

	    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
		for (s = buffer, t = d = 0; *s; s++) {
		    if (isspace(UChar(*s)))
			*s = '\0';
		    else if (t == 0)
			t = s;
		    else if (d == 0 && s != buffer && s[-1] == '\0')
			d = s;
		}
		if (t != 0 && d != 0 && !strcmp(d, p)) {
		    ttype = strdup(t);
		    fclose(fp);
		    goto map;
		}
	    }
	    fclose(fp);
	}
#endif /* HAVE_GETTTYNAM */
    }

    /* If still undefined, use "unknown". */
    ttype = "unknown";

  map:ttype = mapped(ttype);

    /*
     * If not a path, remove TERMCAP from the environment so we get a
     * real entry from /etc/termcap.  This prevents us from being fooled
     * by out of date stuff in the environment.
     */
  found:if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
	/* 'unsetenv("TERMCAP")' is not portable.
	 * The 'environ' array is better.
	 */
	int n;
	for (n = 0; environ[n] != 0; n++) {
	    if (!strncmp("TERMCAP=", environ[n], 8)) {
		while ((environ[n] = environ[n + 1]) != 0) {
		    n++;
		}
		break;
	    }
	}
    }

    /*
     * ttype now contains a pointer to the type of the terminal.
     * If the first character is '?', ask the user.
     */
    if (ttype[0] == '?') {
	if (ttype[1] != '\0')
	    ttype = askuser(ttype + 1);
	else
	    ttype = askuser(0);
    }
    /* Find the terminfo entry.  If it doesn't exist, ask the user. */
    while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret)
	   != OK) {
	if (errret == 0) {
	    (void) fprintf(stderr, "%s: unknown terminal type %s\n",
			   _nc_progname, ttype);
	    ttype = 0;
	} else {
	    (void) fprintf(stderr,
			   "%s: can't initialize terminal type %s (error %d)\n",
			   _nc_progname, ttype, errret);
	    ttype = 0;
	}
	ttype = askuser(ttype);
    }
#if BROKEN_LINKER
    tgetflag("am");		/* force lib_termcap.o to be linked for 'ospeed' */
#endif
    return (ttype);
}
Ejemplo n.º 29
0
Archivo: pam_group.c Proyecto: aosm/pam
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
			      , int argc, const char **argv)
{
    const char *service=NULL, *tty=NULL;
    const char *user=NULL;
    int retval;
    unsigned setting;

    /* only interested in establishing credentials */

    setting = flags;
    if (!(setting & PAM_ESTABLISH_CRED)) {
	D(("ignoring call - not for establishing credentials"));
	return PAM_SUCCESS;            /* don't fail because of this */
    }

    /* set service name */

    if (pam_get_item(pamh, PAM_SERVICE, (const void **)&service)
	!= PAM_SUCCESS || service == NULL) {
	_log_err("cannot find the current service name");
	return PAM_ABORT;
    }

    /* set username */

    if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL
	|| *user == '\0') {
	_log_err("cannot determine the user's name");
	return PAM_USER_UNKNOWN;
    }

    /* set tty name */

    if (pam_get_item(pamh, PAM_TTY, (const void **)&tty) != PAM_SUCCESS
	|| tty == NULL) {
	D(("PAM_TTY not set, probing stdin"));
	tty = ttyname(STDIN_FILENO);
	if (tty == NULL) {
	    _log_err("couldn't get the tty name");
	    return PAM_ABORT;
	}
	if (pam_set_item(pamh, PAM_TTY, tty) != PAM_SUCCESS) {
	    _log_err("couldn't set tty name");
	    return PAM_ABORT;
	}
    }

    if (strncmp("/dev/",tty,5) == 0) {          /* strip leading /dev/ */
	tty += 5;
    }

    /* good, now we have the service name, the user and the terminal name */

    D(("service=%s", service));
    D(("user=%s", user));
    D(("tty=%s", tty));

#ifdef WANT_PWDB

    /* We initialize the pwdb library and check the account */
    retval = pwdb_start();                             /* initialize */
    if (retval == PWDB_SUCCESS) {
	retval = check_account(service,tty,user);      /* get groups */
	(void) pwdb_end();                                /* tidy up */
    } else {
	D(("failed to initialize pwdb; %s", pwdb_strerror(retval)));
	_log_err("unable to initialize libpwdb");
	retval = PAM_ABORT;
    }

#else /* WANT_PWDB */
    retval = check_account(service,tty,user);          /* get groups */
#endif /* WANT_PWDB */

    return retval;
}
Ejemplo n.º 30
0
int
main(int argc, char *argv[])
{
	FILE	*f;
	char	*ptr, *start;
	struct	passwd *pwd;
	char	*term_name;
	int	c;
	int	aflag = 0;
	int	errflg = 0;
	int zflg = 0;
	int Zflg = 0;

	char *zonename = NULL;
	zoneid_t *zoneidlist = NULL;
	uint_t nzids_saved, nzids = 0;

	(void) setlocale(LC_ALL, "");

	while ((c = getopt(argc, argv, "g:az:Z")) != EOF)
		switch (c) {
		case 'a':
			aflag++;
			break;
		case 'g':
			if (gflag) {
				(void) fprintf(stderr,
				    "Only one group allowed\n");
				return (1);
			}
			if ((pgrp = getgrnam(grpname = optarg)) == NULL) {
				(void) fprintf(stderr, "Unknown group %s\n",
				    grpname);
				return (1);
			}
			gflag++;
			break;
		case 'z':
			zflg++;
			zonename = optarg;
			if (getzoneidbyname(zonename) == -1) {
				(void) fprintf(stderr, "Specified zone %s "
				    "is invalid", zonename);
				return (1);
			}
			break;
		case 'Z':
			Zflg++;
			break;
		case '?':
			errflg++;
			break;
		}

	if (errflg) {
		(void) fprintf(stderr,
		    "Usage: wall [-a] [-g group] [-z zone] [-Z] [files...]\n");
		return (1);
	}

	if (zflg && Zflg) {
		(void) fprintf(stderr, "Cannot use -z with -Z\n");
		return (1);
	}

	if (optind < argc)
		infile = argv[optind];

	if (uname(&utsn) == -1) {
		(void) fprintf(stderr, "wall: uname() failed, %s\n",
		    strerror(errno));
		return (2);
	}
	(void) strcpy(systm, utsn.nodename);

	/*
	 * Get the name of the terminal wall is running from.
	 */

	if ((term_name = ttyname(fileno(stderr))) != NULL) {
		/*
		 * skip the leading "/dev/" in term_name
		 */
		(void) strncpy(line, &term_name[5], sizeof (line) - 1);
	}

	if (who[0] == '?') {
		if (pwd = getpwuid(getuid()))
			(void) strncpy(&who[0], pwd->pw_name, sizeof (who));
	}

	f = stdin;
	if (infile) {
		f = fopen(infile, "r");
		if (f == NULL) {
			(void) fprintf(stderr, "Cannot open %s\n", infile);
			return (1);
		}
	}

	start = &mesg[0];
	ptr = start;
	while ((ptr - start) < 3000) {
		size_t n;

		if (fgets(ptr, &mesg[sizeof (mesg)] - ptr, f) == NULL)
			break;
		if ((n = strlen(ptr)) == 0)
			break;
		ptr += n;
	}
	(void) fclose(f);

	/*
	 * If the request is from the rwall daemon then use the caller's
	 * name and host.  We determine this if all of the following is true:
	 *	1) First 5 characters are "From "
	 *	2) Next non-white characters are of the form "name@host:"
	 */
	if (strcmp(line, "???") == 0) {
		char rwho[MAXNAMLEN+1];
		char rsystm[MAXNAMLEN+1];
		char *cp;

		if (strncmp(mesg, "From ", 5) == 0) {
			cp = &mesg[5];
			cp = copy_str_till(rwho, cp, '@', MAXNAMLEN + 1);
			if (rwho[0] != '\0') {
				cp = copy_str_till(rsystm, ++cp, ':',
				    MAXNAMLEN + 1);
				if (rsystm[0] != '\0') {
					(void) strcpy(systm, rsystm);
					(void) strncpy(rwho, who,
					    sizeof (who));
					(void) strcpy(line, "rpc.rwalld");
				}
			}
		}
	}
	(void) time(&tloc);
	(void) strftime(time_buf, sizeof (time_buf),
	    DATE_FMT, localtime(&tloc));

	if (zflg != 0) {
		if ((zoneidlist =
		    malloc(sizeof (zoneid_t))) == NULL ||
		    (*zoneidlist = getzoneidbyname(zonename)) == -1)
			return (errno);
		nzids = 1;
	} else if (Zflg != 0) {
		if (zone_list(NULL, &nzids) != 0)
			return (errno);
again:
		nzids *= 2;
		if ((zoneidlist = malloc(nzids * sizeof (zoneid_t))) == NULL)
			exit(errno);
		nzids_saved = nzids;
		if (zone_list(zoneidlist, &nzids) != 0) {
			(void) free(zoneidlist);
			return (errno);
		}
		if (nzids > nzids_saved) {
			free(zoneidlist);
			goto again;
		}
	}
	if (zflg || Zflg) {
		for (; nzids > 0; --nzids)
			sendmes_tozone(zoneidlist[nzids-1], aflag);
		free(zoneidlist);
	} else
		sendmes_tozone(getzoneid(), aflag);

	return (0);
}