[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: device nodes with udev?



  [Brian May]
> > See bug #87371. The title is wrong. devfs is not the issue,
> > /dev/pts is (I think). I don't think there is any intention to fix
> > the bug. Over 4 years old. Perhaps this is grounds to drop the
> > package from Debian.

[Miles Bader]
> I'd say so.  Or fix the bug.

Kind of quick and dirty, and not particularly tested, since I don't
actually know how to use ttysnoop.

But it's a proof of concept of how easy it is to add unix98 pty support
to an app....
--- ttysnoops.c~	2005-11-10 00:35:18.000000000 -0600
+++ ttysnoops.c	2005-11-10 01:42:48.000000000 -0600
@@ -18,6 +18,7 @@
 	v0.12d  8-4-98 Carl Declerck	- updated #includes a bit
 */
 
+#define _XOPEN_SOURCE /* ptsname() */
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
@@ -54,6 +55,7 @@
 int pgmpid = -1, authpid = -1, servpid = -1;
 int use_socket = 0, fdmax = 0, proctype = DEAD_PROCESS;
 char snoopdev[32], ptynam[32], childproc[128], sockname[128];
+char *short_ptynam, *shorter_ptynam;
 
 
 /* read a single line from a stream, ignoring all irrelevant stuff */
@@ -148,7 +150,17 @@
 }
 
 /* find & open a pty to be used by the pty-master */
+int open_unix98_master (char *ptyname)
+{
+	int fd = open("/dev/ptmx", O_RDWR);
+	char *name = "unknown";
 
+	if (fd >= 0)
+		name = ptsname(fd);
+	if (name)
+		strcpy(ptyname, name);
+	return fd;
+}
 int find_ptyxx (char *ptyname)
 {
 	int fd, i, j;
@@ -180,6 +192,20 @@
 
 /* find & open a pty (tty) to be used by pty-client */
 
+int open_unix98_slave (int ptyfd)
+{
+	int fd;
+	char *name = ptsname(ptyfd);
+
+	grantpt(ptyfd);
+	unlockpt(ptyfd);
+
+	if ((fd = open(name, O_RDWR)) >= 0)
+		return fd;
+
+	close(ptyfd);
+	return -1;
+}
 int find_ttyxx (char *ttyname, int ptyfd)
 {
 	struct group *grp;
@@ -200,23 +226,36 @@
 	return (-1);
 }
 
+void abbreviate_ptyname (char *name, char **shortname, char **shortername)
+{
+	*shortname = *shortername = name;
+	if (!name)
+		return;
+	if (strncmp(name, "/dev/", 5))
+		return;
+	*shortname = *shortername = name + 5;
+	if (!strncmp(name, "/dev/tty", 8))
+		*shortername = name + 8;
+	else if (!strncmp(name, "/dev/pts/", 9))
+		*shortername = name + 9;
+}
+
 /* fork off the pty-client and redirect its stdin/out/err to the pty */
 
 int fork_pty (int *ptyfd, char *ttynam)
 {
 	struct termios term;
 	struct winsize twin;
-	int ttyfd, pid;
-	char name[32];
+	int ttyfd, pid, is_unix98 = 0;
 	
 	tcgetattr (STDIN_FILENO, &term);
 	ioctl (STDIN_FILENO, TIOCGWINSZ, (char *) &twin);
 
-	if ((*ptyfd = find_ptyxx(name)) < 0)
+	if ((*ptyfd = open_unix98_master(ttynam)) >= 0)
+		is_unix98 = 1;
+	else if ((*ptyfd = find_ptyxx(ttynam)) < 0)
 		errorf ("can't open pty\n");
 	
-	strcpy (ttynam, leafname(name));
-	
 	if ((pid = fork()) < 0)
 		errorf ("can't fork\n");
 	
@@ -224,8 +263,12 @@
 	{
 		if (setsid() < 0)
 			errorf ("setsid failed\n");
-		
-		if ((ttyfd = find_ttyxx(name, *ptyfd)) < 0)
+
+		if (is_unix98)
+			ttyfd = open_unix98_slave(*ptyfd);
+		else
+			ttyfd = find_ttyxx(ttynam, *ptyfd);
+		if (ttyfd < 0)
 			errorf ("can't open tty\n");
 			
 		close (*ptyfd);
@@ -384,7 +427,7 @@
 void closedown (void)
 {
 	if (servpid == getpid())	/* only server must clear utmp entry */
-		cleanup_utmp (ptynam);
+		cleanup_utmp (short_ptynam);
 	stty_orig ();
 }
 
@@ -455,14 +498,17 @@
 	
 	/* fork off the client and load the new image */
 	
-	if ((pgmpid = fork_pty(&ptyfd, ptynam)) == 0)    /* child */
+	if ((pgmpid = fork_pty(&ptyfd, ptynam)) < 0)
+		errorf ("cannot fork\n");
+	abbreviate_ptyname(ptynam, &short_ptynam, &shorter_ptynam);
+	if (pgmpid == 0)    /* child */
 	{
 		/* should we update utmp to reflect the change to ttypX ? */
 
 		if (proctype == LOGIN_PROCESS)
 		{
-			strncopy (utmp.ut_line, ptynam);
-			strncopy (utmp.ut_id, ptynam + 3);
+			strncopy (utmp.ut_line, short_ptynam);
+			strncopy (utmp.ut_id, shorter_ptynam);
 			*utmp.ut_host = 0;
 			utmp.ut_addr = 0;
 			strncopy (utmp.ut_user, "LOGIN");
@@ -497,7 +543,7 @@
 		if ((servfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
 			errorf ("can't create server socket\n");
 		
-		sprintf (sockname, "%s/%s", SPOOLDIR, ptynam);
+		sprintf (sockname, "%s/%s", SPOOLDIR, shorter_ptynam);
 		unlink (sockname);
 		serv_addr.sun_family = AF_UNIX;
 		strncopy (serv_addr.sun_path, sockname);

Attachment: signature.asc
Description: Digital signature


Reply to: