# --- SDE-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # Filename: package/.../dietlibc/ttyname_r.diff # Copyright (C) 2009 The OpenSDE Project # # More information can be found in the files COPYING and README. # # This patch file is dual-licensed. It is available under the license the # patched project is licensed under, as long as it is an OpenSource license # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms # of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # --- SDE-COPYRIGHT-NOTE-END --- This patch replaces dietlibc functionality with uClibc equivalent. It is needed because modern software expects ttyname_r function to be available in the C library. --- ./include/unistd.h.orig 2009-11-09 15:39:52.000000000 +0100 +++ ./include/unistd.h 2009-11-09 15:41:48.000000000 +0100 @@ -105,6 +105,10 @@ char *ttyname (int desc) __THROW; +/* Store at most BUFLEN characters of the pathname of the terminal FD is + open on in BUF. Return 0 on success, otherwise an error number. */ +int ttyname_r (int __fd, char *__buf, size_t __buflen) __THROW; + int brk(void *end_data_segment) __THROW; void *sbrk(ptrdiff_t increment) __THROW; --- ./lib/ttyname.c.orig 2002-02-23 23:18:42.000000000 +0100 +++ ./lib/ttyname.c 2009-11-09 15:43:20.000000000 +0100 @@ -1,66 +1,119 @@ -#include "dietfeatures.h" +#include +#include +#include #include +#include #include -#include -#ifdef __linux__ +/* Jan 1, 2004 Manuel Novoa III + * + * Kept the same approach, but rewrote the code for the most part. + * Fixed some minor issues plus (as I recall) one SUSv3 errno case. + */ + +/* This is a fairly slow approach. We do a linear search through some + * directories looking for a match. Yes this is lame. But it should + * work, should be small, and will return names that match what is on + * disk. Another approach we could use would be to use the info in + * /proc/self/fd, but that is even more lame since it requires /proc */ + +/* SUSv3 mandates TTY_NAME_MAX as 9. This is obviously insufficient. + * However, there is no need to waste space and support non-standard + * tty names either. So we compromise and use the following buffer + * length. (Erik and Manuel agreed that 32 was more than reasonable.) + * + * If you change this, also change _SC_TTY_NAME_MAX in libc/unistd/sysconf.c + */ +#define TTYNAME_BUFLEN 32 + +char *ttyname(int fd) +{ + static char name[TTYNAME_BUFLEN]; + + return ttyname_r(fd, name, TTYNAME_BUFLEN) ? NULL : name; +} + +static const char dirlist[] = +/* 12345670123 */ +"\010/dev/vc/\0" /* Try /dev/vc first (be devfs compatible) */ +"\011/dev/tts/\0" /* and /dev/tts next (be devfs compatible) */ +"\011/dev/pty/\0" /* and /dev/pty next (be devfs compatible) */ +"\011/dev/pts/\0" /* and try /dev/pts next */ +"\005/dev/\0"; /* and try walking through /dev last */ + +int ttyname_r(int fd, char *ubuf, size_t ubuflen) +{ + struct dirent *d; + struct stat st; + struct stat dst; + const char *p; + char *s; + DIR *fp; + int rv; + int len; + char buf[TTYNAME_BUFLEN]; + + if (fstat(fd, &st) < 0) { + return errno; + } + + rv = ENOTTY; /* Set up the default return value. */ -#include + if (!isatty(fd)) { + goto DONE; + } -char *ttyname(int fd) { -#ifdef SLASH_PROC_OK - char ibuf[20]; - static char obuf[20]; - int len; - if (!isatty(fd)) return 0; - strcpy(ibuf,"/proc/self/fd/"); - ibuf[__ltostr(ibuf+14,6,(unsigned long)fd,10,0)+14]=0; - if ((len=readlink(ibuf,obuf,sizeof(obuf)-1))<0) return 0; - obuf[len]=0; - return obuf; + for (p = dirlist ; *p ; p += 1 + p[-1]) { + len = *p++; + + assert(len + 2 <= TTYNAME_BUFLEN); /* dirname + 1 char + nul */ + + strcpy(buf, p); + s = buf + len; + len = (TTYNAME_BUFLEN-2) - len; /* Available non-nul space. */ + + if (!(fp = opendir(p))) { + continue; + } + + while ((d = readdir(fp)) != NULL) { + /* This should never trigger for standard names, but we + * check it to be safe. */ + if (strlen(d->d_name) > len) { /* Too big? */ + continue; + } + + strcpy(s, d->d_name); + + if ((lstat(buf, &dst) == 0) +#if 0 + /* Stupid filesystems like cramfs fail to guarantee that + * st_ino and st_dev uniquely identify a file, contrary to + * SuSv3, so we cannot be quite so precise as to require an + * exact match. Settle for something less... Grumble... */ + && (st.st_dev == dst.st_dev) && (st.st_ino == dst.st_ino) #else - static char buf[20]; - struct stat s; - char *c=buf+8; - int n; - if (!isatty(fd)) return 0; - if (fstat(fd,&s)) return 0; - strcpy(buf,"/dev/tty"); - if (S_ISCHR(s.st_mode)) { - n=minor(s.st_rdev); - switch (major(s.st_rdev)) { - case 4: - if (n>63) { - n-=64; - *c='S'; - ++c; - } -num: - c[__ltostr(c,6,n,10,0)]=0; - break; - case 2: - buf[8]='p'-(n>>4); - buf[9]=n%4+'0'; - if (buf[9]>'9') *c+='a'-'0'; - buf[10]=0; - goto duh; - case 136: - case 137: - case 138: - case 139: - buf[7]='s'; -duh: - buf[5]='p'; - n+=(major(s.st_rdev)-136)<<8; - *c='/'; ++c; - goto num; - default: - return 0; - } - return buf; - } - return 0; + && S_ISCHR(dst.st_mode) && (st.st_rdev == dst.st_rdev) #endif + ) { /* Found it! */ + closedir(fp); + + /* We treat NULL buf as ERANGE rather than EINVAL. */ + rv = ERANGE; + if (ubuf && (strlen(buf) <= ubuflen)) { + strcpy(ubuf, buf); + rv = 0; + } + goto DONE; + } + } + + closedir(fp); + } + + DONE: + __set_errno(rv); + + return rv; } -#endif