You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
5.7 KiB
212 lines
5.7 KiB
# --- 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 <string.h> |
|
+#include <errno.h> |
|
+#include <assert.h> |
|
#include <unistd.h> |
|
+#include <dirent.h> |
|
#include <sys/stat.h> |
|
-#include <string.h> |
|
|
|
-#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 <stdlib.h> |
|
+ 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
|
|
|