Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Dec 2013 17:11:24 +0100 (CET)
From:      Tobias Rehbein <tobias.rehbein@web.de>
To:        FreeBSD-gnats-submit@freebsd.org
Cc:        m_evmenkin@yahoo.com
Subject:   bin/184597: [PATCH] Fix rfcomm_sppd pseudo slave TTY mode
Message-ID:  <201312081611.rB8GBOsb002312@oshi.local>
Resent-Message-ID: <201312081620.rB8GK1A0073173@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         184597
>Category:       bin
>Synopsis:       [PATCH] Fix rfcomm_sppd pseudo slave TTY mode
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Dec 08 16:20:01 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Tobias Rehbein
>Release:        FreeBSD 10.0-BETA4 amd64
>Organization:
>Environment:
System: FreeBSD oshi.local 10.0-BETA4 FreeBSD 10.0-BETA4 #0: Tue Dec 3 19:39:08 CET 2013 tobi@oshi.local:/usr/obj/usr/src/sys/GENERIC amd64


	
>Description:
	rfcomm_sppd uses the deprecated pty(4) driver to implement its pseudo slave TTY mode (invoked by the '-t tty' option). This breaks on recent FreeBSD systems. In order to fix this I changed the code to use the openpty(3) API which uses the pts(4) driver instead of the pty(4) driver.

	The patch works fine for me, but there is one regression in functionality: The old code allowed the user to select the name of the pseudo terminal. This no longer works using the pts(4) driver, the name is always automatically selected by the pts(4) driver. But maybe I missed something here.


	
>How-To-Repeat:
	
>Fix:

	

--- rfcomm_sppd-to-pts-openpty.diff begins here ---
diff --git a/usr.bin/bluetooth/rfcomm_sppd/Makefile b/usr.bin/bluetooth/rfcomm_sppd/Makefile
index 9018f6e..0da7498 100644
--- a/usr.bin/bluetooth/rfcomm_sppd/Makefile
+++ b/usr.bin/bluetooth/rfcomm_sppd/Makefile
@@ -6,6 +6,6 @@ SRCS=		rfcomm_sppd.c rfcomm_sdp.c
 WARNS?=		2
 
 DPADD=		${LIBBLUETOOTH} ${LIBSDP}
-LDADD=		-lbluetooth -lsdp
+LDADD=		-lbluetooth -lsdp -lutil
 
 .include <bsd.prog.mk>
diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1 b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
index 92c7d45..38a8153 100644
--- a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
+++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
@@ -33,10 +33,9 @@
 .Nd RFCOMM Serial Port Profile daemon
 .Sh SYNOPSIS
 .Nm
-.Op Fl bhS
+.Op Fl bhtS
 .Fl a Ar address
 .Fl c Ar channel
-.Op Fl t Ar tty
 .Sh DESCRIPTION
 The
 .Nm
@@ -53,7 +52,7 @@ Once connection is established, the
 .Nm
 utility provides access to the server's remote serial port via stdin/stdout
 or via
-.Xr pty 4
+.Xr pts 4
 interface if
 .Fl t
 option was specified.
@@ -72,8 +71,7 @@ daemon.
 If
 .Fl t
 options was specified,
-the server side of the virtual serial port is attached to the pseudo-terminal
-.Ar tty .
+the server side of the virtual serial port is attached to a pseudo-terminal.
 Otherwise the virtual serial port is attached to the stdin/stdout.
 .Nm
 should be run as root in order to communicate with
@@ -146,24 +144,22 @@ Display usage message and exit.
 .It Fl S
 Server mode; see
 .Sx DESCRIPTION .
-.It Fl t Ar tty
-Slave pseudo tty name.
+.It Fl t
+Use slave pseudo tty.
 If not set stdin/stdout will be used.
 This option is required if
 .Fl b
 option was specified.
 .El
 .Sh FILES
-.Bl -tag -width ".Pa /dev/tty[p-sP-S][0-9a-v]" -compact
-.It Pa /dev/pty[p-sP-S][0-9a-v]
-master pseudo terminals
-.It Pa /dev/tty[p-sP-S][0-9a-v]
+.Bl -tag -width ".Pa /dev/pts/[num]" -compact
+.It Pa /dev/pts/[num]
 slave pseudo terminals
 .El
 .Sh EXIT STATUS
 .Ex -std
 .Sh EXAMPLES
-.Dl "rfcomm_sppd -a 00:01:02:03:04:05 -c 1 -t /dev/ttyp1"
+.Dl "rfcomm_sppd -a 00:01:02:03:04:05 -c 1 -t"
 .Pp
 Will start the
 .Nm
@@ -171,13 +167,17 @@ utility and open RFCOMM connection to the server at
 .Li 00:01:02:03:04:05
 and channel
 .Li 1 .
-Once the connection has been established,
-.Pa /dev/ttyp1
+Once the connection has been established, a
+.Xr pts 4
 can be used to talk to the remote serial port on the server.
+.Nm
+prints the name of the
+.Xr pts 4
+to use.
 .Sh SEE ALSO
 .Xr bluetooth 3 ,
 .Xr ng_btsocket 4 ,
-.Xr pty 4 ,
+.Xr pts 4 ,
 .Xr rfcomm_pppd 8 ,
 .Xr sdpd 8
 .Sh AUTHORS
diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
index 4e0d04b..5e426f5 100644
--- a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
+++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
@@ -32,6 +32,7 @@
  */
 
 #include <sys/stat.h>
+#include <sys/types.h>
 #include <bluetooth.h>
 #include <ctype.h>
 #include <err.h>
@@ -49,6 +50,7 @@
 #include <syslog.h>
 #include <termios.h>
 #include <unistd.h>
+#include <libutil.h>
 
 #define SPPD_IDENT		"rfcomm_sppd"
 #define SPPD_BUFFER_SIZE	1024
@@ -58,7 +60,7 @@ int		rfcomm_channel_lookup	(bdaddr_t const *local,
 					 bdaddr_t const *remote, 
 					 int service, int *channel, int *error);
 
-static int	sppd_ttys_open	(char const *tty, int *amaster, int *aslave);
+static int	sppd_ttys_open	(char **tty, int *amaster, int *aslave);
 static int	sppd_read	(int fd, char *buffer, int size);
 static int	sppd_write	(int fd, char *buffer, int size);
 static void	sppd_sighandler	(int s);
@@ -74,7 +76,8 @@ main(int argc, char *argv[])
 	struct sockaddr_rfcomm	 ra;
 	bdaddr_t		 addr;
 	int			 n, background, channel, service,
-				 s, amaster, aslave, fd, doserver;
+				 s, amaster, aslave, fd, doserver,
+				 dopty;
 	fd_set			 rfd;
 	char			*tty = NULL, *ep = NULL, buf[SPPD_BUFFER_SIZE];
 
@@ -82,9 +85,10 @@ main(int argc, char *argv[])
 	background = channel = 0;
 	service = SDP_SERVICE_CLASS_SERIAL_PORT;
 	doserver = 0;
+	dopty = 0;
 
 	/* Parse command line options */
-	while ((n = getopt(argc, argv, "a:bc:t:hS")) != -1) {
+	while ((n = getopt(argc, argv, "a:bc:thS")) != -1) {
 		switch (n) { 
 		case 'a': /* BDADDR */
 			if (!bt_aton(optarg, &addr)) {
@@ -130,11 +134,8 @@ main(int argc, char *argv[])
 			background = 1;
 			break;
 
-		case 't': /* Slave TTY name */
-			if (optarg[0] != '/')
-				asprintf(&tty, "%s%s", _PATH_DEV, optarg);
-			else
-				tty = optarg;
+		case 't': /* Open pseudo TTY */
+			dopty = 1;
 			break;
 
 		case 'S':
@@ -173,18 +174,18 @@ main(int argc, char *argv[])
 		err(1, "Could not sigaction(SIGCHLD)");
 
 	/* Open TTYs */
-	if (tty == NULL) {
+	if (dopty) {
+		if (sppd_ttys_open(&tty, &amaster, &aslave) < 0)
+			exit(1);
+
+		fd = amaster;
+	} else {
 		if (background)
 			usage();
 
 		amaster = STDIN_FILENO;
 		fd = STDOUT_FILENO;
-	} else {
-		if (sppd_ttys_open(tty, &amaster, &aslave) < 0)
-			exit(1);
-		
-		fd = amaster;
-	}		
+	}
 
 	/* Open RFCOMM connection */
 
@@ -359,72 +360,20 @@ main(int argc, char *argv[])
 
 /* Open TTYs */
 static int
-sppd_ttys_open(char const *tty, int *amaster, int *aslave)
+sppd_ttys_open(char **tty, int *amaster, int *aslave)
 {
-	char		 pty[PATH_MAX], *slash;
-	struct group	*gr = NULL;
-	gid_t		 ttygid;
+	char		 pty[PATH_MAX];
 	struct termios	 tio;
 
-	/*
-	 * Construct master PTY name. The slave tty name must be less then
-	 * PATH_MAX characters in length, must contain '/' character and 
-	 * must not end with '/'.
-	 */
-
-	if (strlen(tty) >= sizeof(pty)) {
-		syslog(LOG_ERR, "Slave tty name is too long");
-		return (-1);
-	}
-
-	strlcpy(pty, tty, sizeof(pty));
-	slash = strrchr(pty, '/');
-	if (slash == NULL || slash[1] == '\0') {
-		syslog(LOG_ERR, "Invalid slave tty name (%s)", tty);
-		return (-1);
-	}
-
-	slash[1] = 'p';
-	
-	if (strcmp(pty, tty) == 0) {
-		syslog(LOG_ERR, "Master and slave tty are the same (%s)", tty);
-		return (-1);
-	}
-
-	if ((*amaster = open(pty, O_RDWR, 0)) < 0) {
-		syslog(LOG_ERR, "Could not open(%s). %s", pty, strerror(errno));
-		return (-1);
-	}
-
-	/*
-	 * Slave TTY
-	 */
-
-	if ((gr = getgrnam("tty")) != NULL)
-		ttygid = gr->gr_gid;
-	else
-		ttygid = -1;
-
-	(void) chown(tty, getuid(), ttygid);
-	(void) chmod(tty, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
-	(void) revoke(tty);
+	cfmakeraw(&tio);
 
-	if ((*aslave = open(tty, O_RDWR, 0)) < 0) {
-		syslog(LOG_ERR, "Could not open(%s). %s", tty, strerror(errno));
-		close(*amaster);
+	if (openpty(amaster, aslave, pty, &tio, NULL) == -1) {
+		syslog(LOG_ERR, "Could not openpty(). %s", strerror(errno));
 		return (-1);
 	}
 
-	/*
-	 * Make slave TTY raw
-	 */
-
-	cfmakeraw(&tio);
-
-	if (tcsetattr(*aslave, TCSANOW, &tio) < 0) {
-		syslog(LOG_ERR, "Could not tcsetattr(). %s", strerror(errno));
-		close(*aslave);
-		close(*amaster);
+	if ((*tty = strdup(pty)) == NULL) {
+		syslog(LOG_ERR, "Could not strdup(). %s", strerror(errno));
 		return (-1);
 	}
 
@@ -496,7 +445,7 @@ usage(void)
 "\t-a address Peer address (required in client mode)\n" \
 "\t-b         Run in background\n" \
 "\t-c channel RFCOMM channel to connect to or listen on\n" \
-"\t-t tty     TTY name (required in background mode)\n" \
+"\t-t         use slave pseudo tty (required in background mode)\n" \
 "\t-S         Server mode\n" \
 "\t-h         Display this message\n", SPPD_IDENT);
 	exit(255);
--- rfcomm_sppd-to-pts-openpty.diff ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201312081611.rB8GBOsb002312>