コード例 #1
0
ファイル: login_tty.c プロジェクト: FreeBSDFoundation/freebsd
int
login_tty(int fd)
{
	pid_t s;

	s = setsid();
	if (s == -1)
		s = getsid(0);
	if (tcsetsid(fd, s) == -1)
		return (-1);
	(void) dup2(fd, 0);
	(void) dup2(fd, 1);
	(void) dup2(fd, 2);
	if (fd > 2)
		(void) close(fd);
	return (0);
}
コード例 #2
0
ファイル: ioctl.c プロジェクト: vocho/openqnx
int ioctl(int fd, int cmd, ...) {
    va_list vl;
	void *data;
	struct termios	ltermios;
#ifdef NOT_USED
	struct termios	*ptermios;
	struct termio	ltermio;
#endif
	struct termio	*ptermio;
	int				match, tempint;

	//Pull out the command and the data
	va_start(vl, cmd);
	data = va_arg(vl, void *);
	va_end(vl);

	/* 
     These calls have significantly different inputs or outputs
     that we have to manipulate (or re-direct entirely)
	*/
	switch ((unsigned)cmd) {	
	/**** These calls map to fcntl's ****/

	//Set/Clear FD_CLOEXEC state
	case FIOCLEX:	
		return(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC));
	case FIONCLEX:
		return(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC));

	//These are undoced uses for fcntl
	case SIOCGPGRP:
	case FIOGETOWN:
		if ( (tempint = fcntl (fd, F_GETOWN)) != -1)
			*(int *)data = tempint;
		return(tempint);
	case SIOCSPGRP:
	case FIOSETOWN:
		return(fcntl(fd, F_SETOWN, *(int *)data));

	//Set the non-blocking state for reads on and off
	case FIONBIO:
		if (*(int *)data)
			return(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK));
		else
			return(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK));

	//Set the async state on and off
	case FIOASYNC:
		if (*(int *)data)
			return(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_ASYNC));
		else
			return(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_ASYNC));

	//Set/Clear exclusive mode
	case TIOCEXCL: {
		struct flock lflock;
		memset(&lflock, 0, sizeof(lflock));
		lflock.l_type = F_WRLCK;			//Fails if file opened read only?
		lflock.l_whence = SEEK_SET;
		lflock.l_start = 0;
		lflock.l_len = 0;
		lflock.l_pid = getpid();
		return(__fcntl2ioctl(fcntl(fd, F_SETLK, &lflock)));
	}
	case TIOCNXCL: {
		struct flock lflock;
		memset(&lflock, 0, sizeof(lflock));
		lflock.l_type = F_UNLCK;
		lflock.l_whence = SEEK_SET;
		lflock.l_start = 0;
		lflock.l_len = 0;
		lflock.l_pid = getpid();
		(void)fcntl(fd, F_GETLK, &lflock);
		return(__fcntl2ioctl(fcntl(fd, F_SETLK, &lflock)));
	}

	//Make the terminal the controlling terminal for the process
	case TIOCSCTTY:
		return(tcsetsid(fd, getpid()));
	//Dis-associate this terminal as the controlling terminal
	case TIOCNOTTY:
		return(tcsetsid(-1, getpid()));

	/**** These calls translate from one type to another using tc[s|g]etattr ****/

	//Terminal properties w/ termio
	case TCGETA: {
		ptermio = (struct termio *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		termios2termio(&ltermios, ptermio);
		return(EOK);
	}
	case TCSETA: {
		ptermio = (struct termio *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);		
		termio2termios(ptermio, &ltermios);
		return(tcsetattr(fd, TCSANOW, &ltermios));
	}
	case TCSETAW: {
		ptermio = (struct termio *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);		
		termio2termios(ptermio, &ltermios);
		return(tcsetattr(fd, TCSADRAIN, &ltermios));
	}
	case TCSETAF: {
		ptermio = (struct termio *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);		
		termio2termios(ptermio, &ltermios);
		return(tcsetattr(fd, TCSAFLUSH, &ltermios));
	}

	//Set terminal state in an sgttyb structure (incomplete)
	case TIOCGETP: {
		struct sgttyb *psgttyb = (struct sgttyb *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		termios2sgttyb(&ltermios, psgttyb);
		return(EOK);
	}	
	case TIOCSETP: {
		struct sgttyb *psgttyb = (struct sgttyb *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		sgttyb2termios(psgttyb, &ltermios);
		return(tcsetattr(fd, TCSAFLUSH, &ltermios));
	}
	case TIOCSETN: {
		struct sgttyb *psgttyb = (struct sgttyb *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		sgttyb2termios(psgttyb, &ltermios);
		return(tcsetattr(fd, TCSANOW, &ltermios));
	}

	//Terminal state in tchars structure
	case TIOCGETC: {
		struct tchars *ptchars = (struct tchars *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		termios2tchars(&ltermios, ptchars);
		return(EOK);
	}
	case TIOCSETC: {
		struct tchars *ptchars = (struct tchars *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		tchars2termios(ptchars, &ltermios);
		return(tcsetattr(fd, TCSANOW, &ltermios));
	}
	
	//Terminal state in an ltchars structure
	case TIOCGLTC: {
		struct ltchars *pltchars = (struct ltchars *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		termios2ltchars(&ltermios, pltchars);
		return(EOK);
	}
	case TIOCSLTC: {
		struct ltchars *pltchars = (struct ltchars *)data;
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		ltchars2termios(pltchars, &ltermios);
		return(tcsetattr(fd, TCSANOW, &ltermios));
	}

	//Set/Get the local flags structure
	case TIOCLGET: {
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		*((int *)data) = (int)ltermios.c_lflag;
		return(EOK);
	}
	case TIOCLSET: {
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		ltermios.c_lflag &= ~0xffff;
		ltermios.c_lflag |= *((int*)data);
		return(tcsetattr(fd, TCSANOW, &ltermios));
	}

	//Clear the break flag (implement TIOCSBRK?)
	case TIOCCBRK: {
		if (tcgetattr(fd, &ltermios) == -1)
			return(-1);
		ltermios.c_iflag &= ~(BRKINT);
		ltermios.c_iflag |= IGNBRK;
		return(tcsetattr(fd, TCSANOW, &ltermios));
	}

	//Set the HUPCL flag 
	case TIOCHPCL: {
		if (tcgetattr(fd, &ltermios) != -1) {
			ltermios.c_cflag |= HUPCL;
			return(tcsetattr(fd, TCSANOW, &ltermios));
		}
	}

	/**** These calls map to devctl's, but need serious data munging ****/

	//Inject a character into the stream
	case TIOCSTI: {	
		return(tcinject(fd, (char*)data, sizeof(char)));
	}

	//Send a break for a period of time
	case TCSBRK: {
		int *duration = (int *) data;				//Duration is measured in ms 
		return(tcsendbreak(fd, *duration));
		//tempint = (((*duration) ? *duration : 300) << 16) | _SERCTL_BRK_CHG | _SERCTL_BRK;
		//return(devctl(fd, DCMD_CHR_SERCTL, &tempint, sizeof(tempint), &ret));
	}

	/**** Modem control operations (via devctl) ****/
	//Clear the state of the modem by ~AND'ing in the int argument
	case TIOCMBIC: {
		int tmpmodem;
		if (_devctl(fd, DCMD_CHR_LINESTATUS, &tmpmodem, sizeof(tmpmodem), _DEVCTL_FLAG_NOTTY) == -1) 
			return(-1);
		tmpmodem &= ~(*((int*)data));
		tempint = 0;
		modem2serctl(&tmpmodem, &tempint);
		return(_devctl(fd, DCMD_CHR_SERCTL, &tempint, sizeof(tempint), _DEVCTL_FLAG_NOTTY)); 
	}
	//Set the state of the modem by OR'ing in the int argument
	case TIOCMBIS: {
		int tmpmodem;
		if (_devctl(fd, DCMD_CHR_LINESTATUS, &tmpmodem, sizeof(tmpmodem), _DEVCTL_FLAG_NOTTY) == -1) 
			return(-1);
		tmpmodem |= *((int*)data);		
		tempint = 0;
		modem2serctl(&tmpmodem, &tempint);
		return(_devctl(fd, DCMD_CHR_SERCTL, &tempint, sizeof(tempint), _DEVCTL_FLAG_NOTTY)); 
	}

	//Set the state of the modem lines
	case TIOCMSET: {
		tempint = 0;
		modem2serctl((int*)data, &tempint);
		return(_devctl(fd, DCMD_CHR_SERCTL, &tempint, sizeof(tempint), _DEVCTL_FLAG_NOTTY)); 
	}

	//Set/Clear DTR lines
	case TIOCCDTR: {
		int status; 
		if (_devctl(fd, DCMD_CHR_LINESTATUS, &status, sizeof(status), _DEVCTL_FLAG_NOTTY) == -1)
			return(-1);
		if (status & _LINESTATUS_SER_DTR) {
			status =  _SERCTL_DTR_CHG;
			return(_devctl(fd, DCMD_CHR_SERCTL, &status, sizeof(status), _DEVCTL_FLAG_NOTTY));
		}
		return(EOK);
	}
	case TIOCSDTR: {
		int status; 
		if (_devctl(fd, DCMD_CHR_LINESTATUS, &status, sizeof(status), _DEVCTL_FLAG_NOTTY) == -1)
			return(-1);
		if (!(status & _LINESTATUS_SER_DTR)) {
			status =  _SERCTL_DTR | _SERCTL_DTR_CHG;
			return(_devctl(fd, DCMD_CHR_SERCTL, &status, sizeof(status), _DEVCTL_FLAG_NOTTY));
		}
		return(EOK);
	}
	default:
		break;
	}

/*
 * The following block can go away when 6.4 is released
 * and <sys/sockio.h> from the networking project is
 * generally available.
 */
#ifndef NOSIOCGIFCONF
/* Define these as in the latest <sys/sockio.h> */
#define NOSIOCGIFCONF _IOWR('i', 36, struct ifconf)
#undef SIOCGIFCONF
#define SIOCGIFCONF   _IOWR('i', 38, struct ifconf)
#endif
	/* 
	 Generic handling for all but SIOCGIFCONF networking IOCTL's
	*/
	if ((unsigned)cmd == SIOCGIFCONF || (unsigned)cmd == NOSIOCGIFCONF) {
		io_devctl_t		msg;
		iov_t			wiov[2], riov[3];
		struct ifconf *ifconfp = (struct ifconf *)data;

		msg.i.type = _IO_DEVCTL;
		msg.i.combine_len = sizeof(msg.i);
		msg.i.dcmd = cmd;
		msg.i.zero = 0;
		msg.i.nbytes = ifconfp->ifc_len;

		SETIOV (wiov + 0, &msg, sizeof (msg.i));
		SETIOV (wiov + 1, data, IOCPARM_LEN((unsigned)cmd));
		SETIOV (riov + 0, &msg, sizeof (msg.o));
		SETIOV (riov + 1, ifconfp, sizeof (ifconfp->ifc_len));
		SETIOV (riov + 2, ifconfp->ifc_buf, ifconfp->ifc_len);
		return MsgSendv(fd, wiov, 2, riov, 3);
	}

	/* 
	 These calls require their command types to be translated
	*/
	switch ((unsigned)cmd) {
	case TCGETS:								//Not on NetBSD 
		SETNEWNUM(cmd, TIOCGETA);  match = 1;
		break;

	case TCSETS:								//Not on NetBSD
		SETNEWNUM(cmd, TIOCSETA);  match = 1; 
		break;

	case TCSETSW:								//Not on NetBSD
		SETNEWNUM(cmd, TIOCSETAW);  match = 1;
		break;

	case TCSETSF:								//Not on NetBSD
		SETNEWNUM(cmd, TIOCSETAF);  match = 1;
		break;

	case TIOCSETPGRP:							//Not on Sun
		SETNEWNUM(cmd, TIOCSPGRP);  match = 1;
		break;

	case TIOCGETPGRP:							//Not on Sun
		SETNEWNUM(cmd, TIOCGPGRP);  match = 1; 
		break;

	case TIOCSTOP: 
	case TIOCSTART:							
		//These functions pass in void but we need to pass an int so ...
		data = &tempint;
		tempint = (cmd == TIOCSTOP) ? TCOOFF : TIOCSTART;
		cmd = _IOW(_DCMD_CHR,TCXONC,int);		//Create new command  
	case TCXONC:								//Not on NetBSD
		//Assume incoming data already looks like:
		//data = 0= suspend output = TCOOFF, 1= restart output = TCOON
		//       2= suspend input = TCIOFF,  3= restart input = TCION
		SETNEWNUM(cmd, TCXONC);  match = 1;
		break;

	case TIOCFLUSH: 
		//Need to re-map 0 -> 2, FREAD -> 0, FWRITE -> 1
		switch (*((int*)data)) {
			case 0:      *((int*)data) = TCIOFLUSH; break;
			case FREAD:  *((int*)data) = TCIFLUSH; break;
			case FWRITE: *((int*)data) = TCOFLUSH; break;
			default: break;
		}
		/* Fall Through */
	case TCFLSH:								//Not on NetBSD 
		//Assume input data looks like:
		//data = 0 = flush in, 1 = flush output, 2 = flush both
		SETNEWNUM(cmd, TIOCFLUSH); match = 1;
		break;

	default:
		break;
	}

	//If you got this far then out you go as a generic devctl
	return(_devctl(fd, cmd, data, IOCPARM_LEN((unsigned)cmd), _DEVCTL_FLAG_NOTTY));
	/*
	 Returns different things for different commands:
	 - GETPRGRP returns pid_t 
	 - FIOREAD returns number of chars in input queue
	 - TIOCOUTQ returns number of chars in output queue
	 - 0 for all other cases
	*/
}