/* Store at most BUFLEN characters of the pathname of the slave pseudo terminal associated with the master FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ptsname_r (int fd, char *buf, size_t buflen) { int save_errno = errno; struct stat st; if (buf == NULL) { __set_errno (EINVAL); return EINVAL; } if (!__isatty (fd)) /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY). */ return errno; if (buflen < sizeof (_PATH_PTY) + 4) { __set_errno (ERANGE); return ERANGE; } if (__ttyname_r (fd, buf, buflen) != 0) return errno; buf[ 9] = 's'; buf[10] = 'l'; buf[11] = 'v'; if (__stat (buf, &st) < 0) return errno; __set_errno (save_errno); return 0; }
/*------------------------------------------- | Name:__io_init_vars | Description: | Parameters: | Return Type: | Comments: | See: ---------------------------------------------*/ void __io_init_vars(){ static int first_time = 1; if( !first_time ) return; first_time = 1; if (__isatty(1)) stdout->mode |= _IOLBF; //atexit(__stdio_close_all);//to do: restore atexit }
/* Return the pathname of the terminal FD is open on, or NULL on errors. The returned storage is good only until the next call to this function. */ char * ttyname (int fd) { struct stat st; int dostat = 0; char *name; int save = errno; if (!__isatty (fd)) return NULL; if (fstat (fd, &st) < 0) return NULL; #ifdef _STATBUF_ST_RDEV name = getttyname (fd, st.st_rdev, st.st_ino, save, &dostat); #else name = getttyname (fd, st.st_dev, st.st_ino, save, &dostat); #endif if (!name && dostat != -1) { dostat = 1; #ifdef _STATBUF_ST_RDEV name = getttyname (fd, st.st_rdev, st.st_ino, save, &dostat); #else name = getttyname (fd, st.st_dev, st.st_ino, save, &dostat); #endif } return name; }
/* erase to the end of current line */ void erase_eol() { if (__isatty(1)) { /* printf("\x1b[M"); */ printf("\x1b[K"); } }
/* Return the result of isatty, without changing errno. */ static int local_isatty (int fd) { int save_errno = errno; int res = __isatty (fd); __set_errno (save_errno); return res; }
/* Store at most BUFLEN character 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) { struct stat st; int dostat = 0; int save = errno; int ret; /* Test for the absolute minimal size. This makes life easier inside the loop. */ if (!buf) { __set_errno (EINVAL); return EINVAL; } if (buflen < (int) (sizeof (dev) + 1)) { __set_errno (ERANGE); return ERANGE; } if (!__isatty (fd)) { __set_errno (ENOTTY); return ENOTTY; } if (fstat (fd, &st) < 0) return errno; /* Prepare the result buffer. */ memcpy (buf, dev, sizeof (dev) - 1); buf[sizeof (dev) - 1] = '/'; buflen -= sizeof (dev); #ifdef _STATBUF_ST_RDEV ret = getttyname_r (fd, buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (fd, buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif if (ret && dostat != -1) { dostat = 1; #ifdef _STATBUF_ST_RDEV ret = getttyname_r (fd, buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (fd, buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } return ret; }
/* set stdin to non-canonical mode */ void peekkey_prep() { if (__isatty(0)) { struct termios tio_new; if (tcgetattr(0, &tio_orig) == 0) { memcpy(&tio_new, &tio_orig, sizeof(struct termios)); tio_new.c_lflag = 0; tio_new.c_cc[VMIN] = 0; tio_new.c_cc[VTIME] = 0; if (tcsetattr(0, TCSANOW, &tio_new) == 0) { noncanonical = 1; } } } }
/* Initialize STREAM as necessary. This may change I/O functions, give a buffer, etc. If no buffer is allocated, but the bufsize is set, the bufsize will be used to allocate the buffer. */ void __stdio_init_stream (FILE *stream) { const int fd = (int) stream->__cookie; struct stat statb; if (stream->__buffer != NULL || stream->__userbuf) /* If's unbuffered by request, we can't do anything useful. */ return; /* Find out what sort of file this is. */ if (__fstat (fd, &statb) < 0) return; if (S_ISCHR (statb.st_mode)) { /* It's a character device. Make it line-buffered if it's a terminal. */ if (__isatty (fd)) { stream->__linebuf = 1; /* Unix terminal devices have the bad habit of claiming to be seekable. On systems I have tried, seeking on a terminal device seems to set its file position as specified, such that a later tell says the same thing. This is in no way related to actual seekability--the ability to seek back and read old data. Unix terminal devices will let you "seek back", and then read more new data from the terminal. I can think of nothing to do about this lossage except to preemptively disable seeking on terminal devices. */ stream->__io_funcs.__seek = NULL; /* Seeks get ESPIPE. */ } } #ifdef _STATBUF_ST_BLKSIZE /* Use the block-size field to determine the system's optimal buffering size. */ stream->__bufsize = statb.st_blksize; #endif }
/* Return the pathname of the terminal FD is open on, or NULL on errors. The returned storage is good only until the next call to this function. */ char * ttyname (int fd) { struct stat64 st; char *name; int save = errno; if (!__isatty (fd)) return NULL; if (__fxstat64 (_STAT_VER, fd, &st) < 0) return NULL; name = getttyname ("/dev/pty/slv", st.st_dev, st.st_ino, save); if (!name) { name = getttyname ("/dev/pty/mst", st.st_dev, st.st_ino, save); } return name; }
/* Store at most BUFLEN characters of the pathname of the slave pseudo terminal associated with the master FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ptsname_r (int fd, char *buf, size_t buflen) { int save_errno = errno; int err; struct stat st; if (buf == NULL) { __set_errno (EINVAL); return EINVAL; } if (!__isatty (fd)) /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY). */ return errno; if (buflen < strlen (_PATH_TTY) + 3) { __set_errno (ERANGE); return ERANGE; } err = __ttyname_r (fd, buf, buflen); if (err != 0) { __set_errno (err); return errno; } buf[sizeof (_PATH_DEV) - 1] = 't'; if (__stat (buf, &st) < 0) return errno; __set_errno (save_errno); return 0; }
/* Store at most BUFLEN character 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) { struct stat64 st; int save = errno; int ret; if (buflen < sizeof ("/dev/pty/slv/")) { __set_errno (ERANGE); return ERANGE; } if (!__isatty (fd)) { __set_errno (ENOTTY); return ENOTTY; } if (__fxstat64 (_STAT_VER, fd, &st) < 0) return errno; /* Prepare the result buffer. */ memcpy (buf, "/dev/pty/slv/", sizeof ("/dev/pty/slv/")); buflen -= sizeof ("/dev/pty/slv/") - 1; ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save); if (ret) { memcpy (buf, "/dev/pty/mst/", sizeof ("/dev/pty/mst/")); ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save); } return ret; }
/*------------------------------------------- | Name:__fopen | Description: | Parameters: | Return Type: | Comments:This Fopen is all three of fopen, | fdopen and freopen. The macros in | stdio.h show the other names. | See: ---------------------------------------------*/ FILE * __fopen(const char *fname,int fd,FILE *fp,char *mode) { int open_mode = 0; #if __MODE_IOTRAN int do_iosense = 1; #endif int fopen_mode = 0; FILE *nfp = 0; /* If we've got an fp close the old one (freopen) */ if (fp) { /* Careful, don't de-allocate it */ fopen_mode |= (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF)); fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF); __fclose(fp); } /* decode the new open mode */ while (*mode) switch (*mode++) { case 'r': fopen_mode |= __MODE_READ; break; case 'w': fopen_mode |= __MODE_WRITE; open_mode = (O_CREAT | O_TRUNC); break; case 'a': fopen_mode |= __MODE_WRITE; open_mode = (O_CREAT | O_APPEND); break; case '+': fopen_mode |= __MODE_RDWR; break; #if __MODE_IOTRAN case 'b': /* Binary */ fopen_mode &= ~__MODE_IOTRAN; do_iosense=0; break; case 't': /* Text */ fopen_mode |= __MODE_IOTRAN; do_iosense=0; break; #endif } /* Add in the read/write options to mode for open() */ switch (fopen_mode & (__MODE_READ | __MODE_WRITE)) { case 0: return 0; case __MODE_READ: open_mode |= O_RDONLY; break; case __MODE_WRITE: open_mode |= O_WRONLY; break; default: open_mode |= O_RDWR; break; } /* Allocate the (FILE) before we do anything irreversable */ if (fp == 0) { nfp = malloc(sizeof(FILE)); if (nfp == 0) return 0; } /* Open the file itself */ if (fname) fd = open(fname, open_mode, 0666); if (fd < 0) /* Grrrr */ { if (nfp) free(nfp); return 0; } /* If this isn't freopen create a (FILE) and buffer for it */ if (fp == 0) { fp = nfp; fp->next = __IO_list; __IO_list = fp; fp->mode = __MODE_FREEFIL; if( __isatty(fd) ) { fp->mode |= _IOLBF; #if __MODE_IOTRAN if( do_iosense ) fopen_mode |= __MODE_IOTRAN; #endif } else fp->mode |= _IOFBF; fp->bufstart = malloc(BUFSIZ); if (fp->bufstart == 0) /* Oops, no mem */ { /* Humm, full buffering with a two(!) byte * buffer. */ fp->bufstart = fp->unbuf; fp->bufend = fp->unbuf + sizeof(fp->unbuf); } else { fp->bufend = fp->bufstart + BUFSIZ; fp->mode |= __MODE_FREEBUF; } } /* Ok, file's ready clear the buffer and save important bits */ fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; fp->mode |= fopen_mode; fp->fd = fd; return fp; }
/* Store at most BUFLEN characters of the pathname of the slave pseudo terminal associated with the master FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ptsname_r (int fd, char *buf, size_t buflen) { int save_errno = errno; int err; struct stat st; if (buf == NULL) { __set_errno (EINVAL); return EINVAL; } #if defined __sun /* Solaris */ if (fstat (fd, &st) < 0) return errno; if (!(S_ISCHR (st.st_mode) && major (st.st_rdev) == 0)) { errno = ENOTTY; return errno; } { /* Master ptys can be recognized through a STREAMS ioctl. See "STREAMS-based Pseudo-Terminal Subsystem" <http://docs.oracle.com/cd/E18752_01/html/816-4855/termsub15-44781.html> and "STREAMS ioctl commands" <http://docs.oracle.com/cd/E18752_01/html/816-5177/streamio-7i.html> */ struct strioctl ioctl_arg; ioctl_arg.ic_cmd = ISPTM; ioctl_arg.ic_timout = 0; ioctl_arg.ic_len = 0; ioctl_arg.ic_dp = NULL; if (ioctl (fd, I_STR, &ioctl_arg) < 0) { errno = ENOTTY; return errno; } } { char tmpbuf[9 + 10 + 1]; int n = sprintf (tmpbuf, "/dev/pts/%u", minor (st.st_rdev)); if (n >= buflen) { errno = ERANGE; return errno; } memcpy (buf, tmpbuf, n + 1); } #elif defined _AIX || defined __osf__ /* AIX, OSF/1 */ /* This implementation returns /dev/pts/N, like ptsname() does. Whereas the generic implementation below returns /dev/ttypN. Both are correct, but let's be consistent with ptsname(). */ if (fstat (fd, &st) < 0) return errno; if (!S_ISCHR (st.st_mode)) { errno = ENOTTY; return errno; } { int ret; int dev; char tmpbuf[9 + 10 + 1]; int n; # ifdef _AIX ret = ioctl (fd, ISPTM, &dev); # endif # ifdef __osf__ ret = ioctl (fd, ISPTM, NULL); dev = ret; # endif if (ret < 0) { errno = ENOTTY; return errno; } n = sprintf (tmpbuf, "/dev/pts/%u", minor (dev)); if (n >= buflen) { errno = ERANGE; return errno; } memcpy (buf, tmpbuf, n + 1); } #else if (!__isatty (fd)) { #if ISATTY_FAILS_WITHOUT_SETTING_ERRNO && defined F_GETFL /* IRIX, Solaris */ /* Set errno. */ if (fcntl (fd, F_GETFL) != -1) errno = ENOTTY; #else /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY). */ #endif return errno; } if (buflen < strlen (_PATH_TTY) + 3) { __set_errno (ERANGE); return ERANGE; } err = __ttyname_r (fd, buf, buflen); if (err != 0) { __set_errno (err); return errno; } if (strncmp(buf, "/dev/pts/", strlen("/dev/pts/")) != 0) buf[sizeof (_PATH_DEV) - 1] = 't'; #endif if (__stat (buf, &st) < 0) return errno; __set_errno (save_errno); return 0; }
int __ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp) { int save_errno = errno; unsigned int ptyno; if (buf == NULL) { __set_errno (EINVAL); return EINVAL; } if (!__isatty (fd)) { __set_errno (ENOTTY); return ENOTTY; } #ifdef TIOCGPTN if (__ioctl (fd, TIOCGPTN, &ptyno) == 0) { /* Buffer we use to print the number in. For a maximum size for `int' of 8 bytes we never need more than 20 digits. */ char numbuf[21]; const char *devpts = _PATH_DEVPTS; const size_t devptslen = strlen (_PATH_DEVPTS); char *p; numbuf[sizeof (numbuf) - 1] = '\0'; p = _itoa_word (ptyno, &numbuf[sizeof (numbuf) - 1], 10, 0); if (buflen < devptslen + (&numbuf[sizeof (numbuf)] - p)) { __set_errno (ERANGE); return ERANGE; } memcpy (__stpcpy (buf, devpts), p, &numbuf[sizeof (numbuf)] - p); } else if (errno != EINVAL) return errno; else #endif { char *p; if (buflen < strlen (_PATH_TTY) + 3) { __set_errno (ERANGE); return ERANGE; } if (__fxstat64 (_STAT_VER, fd, stp) < 0) return errno; /* Check if FD really is a master pseudo terminal. */ if (! MASTER_P (stp->st_rdev)) { __set_errno (ENOTTY); return ENOTTY; } ptyno = minor (stp->st_rdev); if (ptyno / 16 >= strlen (__libc_ptyname1)) { __set_errno (ENOTTY); return ENOTTY; } p = __stpcpy (buf, _PATH_TTY); p[0] = __libc_ptyname1[ptyno / 16]; p[1] = __libc_ptyname2[ptyno % 16]; p[2] = '\0'; } if (__xstat64 (_STAT_VER, buf, stp) < 0) return errno; /* Check if the name we're about to return really corresponds to a slave pseudo terminal. */ if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev)) { /* This really is a configuration problem. */ __set_errno (ENOTTY); return ENOTTY; } __set_errno (save_errno); return 0; }
/* move cursor up */ void cursor_up(int rows) { if (__isatty(1)) { printf("\x1b[%dA", rows); } }
/* Store at most BUFLEN character 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) { char procname[30]; struct stat64 st, st1; int dostat = 0; int save = errno; int ret; /* Test for the absolute minimal size. This makes life easier inside the loop. */ if (!buf) { __set_errno (EINVAL); return EINVAL; } if (buflen < sizeof ("/dev/pts/")) { __set_errno (ERANGE); return ERANGE; } /* We try using the /proc filesystem. */ *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0'; ret = __readlink (procname, buf, buflen - 1); if (ret == -1 && errno == ENOENT) { __set_errno (EBADF); return EBADF; } if (!__isatty (fd)) { __set_errno (ENOTTY); return ENOTTY; } if (ret == -1 && errno == ENAMETOOLONG) { __set_errno (ERANGE); return ERANGE; } if (ret != -1 && buf[0] != '[') { buf[ret] = '\0'; return 0; } if (__fxstat64 (_STAT_VER, fd, &st) < 0) return errno; /* Prepare the result buffer. */ memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/")); buflen -= sizeof ("/dev/pts/") - 1; if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode)) { #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } else { __set_errno (save); ret = ENOENT; } if (ret && dostat != -1) { buf[sizeof ("/dev/") - 1] = '\0'; buflen += sizeof ("pts/") - 1; #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } if (ret && dostat != -1) { buf[sizeof ("/dev/") - 1] = '\0'; dostat = 1; #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } return ret; }