From owner-freebsd-current@FreeBSD.ORG Thu Mar 3 02:16:10 2005 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id EB1AE16A4D0 for ; Thu, 3 Mar 2005 02:16:09 +0000 (GMT) Received: from mx2.synetsystems.com (mx2.synetsystems.com [216.226.140.79]) by mx1.FreeBSD.org (Postfix) with ESMTP id EFF9E43D39 for ; Thu, 3 Mar 2005 02:16:08 +0000 (GMT) (envelope-from rmtodd@ichotolot.servalan.com) Received: by mx2.synetsystems.com (Postfix, from userid 66) id 1BB663284; Wed, 2 Mar 2005 21:16:08 -0500 (EST) Received: from localhost ([127.0.0.1]:57263 helo=ichotolot.servalan.com) by servalan.servalan.com with esmtp (Exim 4.44 (FreeBSD)) id 1D6fIz-000K0l-3C for freebsd-current@freebsd.org; Wed, 02 Mar 2005 19:39:09 -0600 To: freebsd-current@freebsd.org Date: Wed, 02 Mar 2005 19:39:09 -0600 From: Richard Todd Message-Id: <20050303021608.1BB663284@mx2.synetsystems.com> Subject: Recent major number changes on ptys break grantpt() and friends in lib/libc/stdlib/grantpt.c X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Mar 2005 02:16:10 -0000 Last night I upgraded my system to the then-current -CURRENT (upgrading from -CURRENT as of a couple weeks ago), installing new kernel and world. Soon after, I discovered that a Perl script of mine I use to pry statistics out of my Netgear router (telneting to the router under a pseudo-tty with p5-Expect and p5-IO-Tty) was giving me the following error messages: IO::Tty::pty_allocate(nonfatal): grantpt(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, line 1. IO::Tty::pty_allocate(nonfatal): unlockpt(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, line 1. IO::Tty::open_slave(nonfatal): ptsname(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, line 1. pty_allocate(nonfatal): openpty(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, line 1. IO::Tty::pty_allocate(nonfatal): grantpt(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, line 1. IO::Tty::pty_allocate(nonfatal): unlockpt(): Invalid argument at /usr/local/lib/perl5/site_perl/5.8.6/mach/IO/Pty.pm line 24, line 1. Further investigation with simplifed test cases revealed that yes indeed, calls by the p5-IO-Tty module to the grantpt()/unlockpt()/ptsname() were failing. Looking at the code for these functions, it's easy to see why. These functions all check to see if the fd they're passed is a valid pty by fstat()ing the fd, looking at the device number, and checking it is a pseudoterminal device node with the ISPTM macro as follows: #define PTM_MAJOR 6 /* pseudo tty master major */ #define PTS_MAJOR 5 /* pseudo tty slave major */ #define PTM_PREFIX "pty" /* pseudo tty master naming convention */ #define PTS_PREFIX "tty" /* pseudo tty slave naming convention */ /* * The following are range values for pseudo TTY devices. Pseudo TTYs have a * name of /dev/[pt]ty[p-sP-S][0-9a-v], yielding 256 combinations per major. */ #define PT_MAX 256 #define PT_DEV1 "pqrsPQRS" #define PT_DEV2 "0123456789abcdefghijklmnopqrstuv" /* * grantpt(3) support utility. */ #define _PATH_PTCHOWN "/usr/libexec/pt_chown" /* * ISPTM(x) returns 0 for struct stat x if x is not a pty master. * The bounds checking may be unnecessary but it does eliminate doubt. */ #define ISPTM(x) (S_ISCHR((x).st_mode) && \ major((x).st_rdev) == PTM_MAJOR && \ minor((x).st_rdev) >= 0 && \ minor((x).st_rdev) < PT_MAX) Yep. The pty master/slave major numbers are hardwired into grantpt.c, and now that pty major device numbers are dynamically allocated, the actual device numbers on a running system don't match what's in the above #define: crw-rw-rw- 1 root wheel 216, 0 Mar 2 01:50 /dev/ptyp0 crw--w---- 1 rmtodd tty 215, 0 Mar 2 01:51 /dev/ttyp0 I managed to work around the immediate problem and stop my script from complaining by bludgeoning the p5-IO-Tty Makefile.PL with a blunt instrument to make it think this system didn't support grantpt() etc. (causing the module to fall back to other methods of dealing with ptys). The proper fix for grantpt.c is less clear, though. Changing it to figure the proper pty major number by stating a known pty node (say, /dev/ptyp0) would work, but from what I understand that's going to break when phk commits his forthcoming patch which will make the whole concept of major numbers go away. Any ideas?