#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
struct devdir
{
struct devdir *d_next;
char *d_name;
};
static struct devdir *head;
static struct devdir *tail;
static char pathname[_POSIX_PATH_MAX+1];
static void add(char *dirname)
{
struct devdir *ddp;
int len;
len=strlen(dirname);
if((dirname[len-1]=='.')&&(dirname[len-2]=='/')||((dirname[len-2]=='.'&&dirname[len-3]='/')))
return;
if(strcmp(dirname, "/dev/fd")==0)
return;
if((ddp=malloc(sizeof(struct devdir)))==NULL)
return;
if((ddp->d_namestrdup(dirname))==NULL)
{
free(ddp);
return;
}
ddp->d_next=NULL;
if(tail==NULL)
{
head=ddp;
tail=ddp;
}
else{
tail=d_next=ddp;
tail=ddp;
}
}
static char * searchdir(char *dirname, struct stat *fdstatp)
{
struct stat devstat;
DIR *dp;
int devlen;
struct dirent *dirp;
strcpy(pathname, dirname);
if((dp=opendir(dirname))==NULL)
return NULL;
strcat(pathname, "/");
devlen=strlen(pathname);
while((dirp=readdir(dp))!=NULL)
{
strncpy(pathname+devlen, dirp->d_name, _POSIX_PATH_MAX-devlen);
if(strcmp(pathname, "/dev/stdin")==0
||strcmp(pathname,"/dev/stdout")==0
||strcmp(pathname,"/dev/stderr")==0)
continue;
if(stat(pathname, &devstat)<0)
continue;
if(S_ISDIR(devstat.st_mode)){
add(pathname);
continue;
}
if(devstat.st_ino==fdstatp->st_ino&&
devstat.st_dev==fdstatp->st_dev)
{
closedir(dp);
return pathname;
}
}
closedir(dp);
return NULL;
}
char *ttypname(int fd)
{
struct stat fdstat;
struct devdir *ddp;
char *rval;
if(isatty(fd)==0)
return NULL;
if(fstat(fd, &fdstat)<0)
return NULL;
if(S_ISCHR(fdstat.st_mode)==0)
return NULL;
rval=searchdir("/dev",&fdstat);
if(rval==NULL)
{
for(ddp=head;ddp!=NULL;ddp=ddp->d_next)
if((rval=searchdir(ddp->d_name, &fdstat))!=NULL)
break;
}
cleanup();
return rval;
}
Implementation of POSIX.1 ttyname function