programing

stdin이 단자인지 파이프인지 검출할 수 있습니까?

bestcode 2022. 7. 21. 00:36
반응형

stdin이 단자인지 파이프인지 검출할 수 있습니까?

"를 실행할 때python인수 없이 단말기에서 Python 인터랙티브셸을 기동합니다.

"를 실행할 때cat | python단말기에서 인터랙티브모드는 기동하지 않습니다.어떻게 된 일인지 아무런 입력도 받지 않고 파이프에 접속되어 있는 것을 검출했습니다.

C, C++ 또는 Qt에서도 같은 검출을 어떻게 하면 좋을까요?

사용하다isatty:

#include <stdio.h>
#include <io.h>
...    
if (isatty(fileno(stdin)))
    printf( "stdin is a terminal\n" );
else
    printf( "stdin is a file or a pipe\n");

(창에서는 밑줄 앞에 다음과 같이 표시됩니다._isatty,_fileno)

요약

많은 사용 사례에서 POSIX 기능은 stdin이 단말기에 연결되어 있는지 감지하는 데 필요한 모든 것입니다.최소한의 예:

#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  if (isatty(fileno(stdin)))
    puts("stdin is connected to a terminal");
  else
    puts("stdin is NOT connected to a terminal");
  return 0;
}

다음 섹션에서는 서로 다른 수준의 인터랙티브를 테스트해야 할 경우 사용할 수 있는 다양한 방법을 비교합니다.

자세한 방법

프로그램이 대화식으로 실행되고 있는지 여부를 감지하는 방법은 여러 가지가 있습니다.다음 표에 개요를 나타냅니다.

cmd\method             ctermid    open   isatty   fstat
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
./test                 /dev/tty   OK     YES      S_ISCHR
./test < test.cc       /dev/tty   OK     NO       S_ISREG
cat test.cc | ./test   /dev/tty   OK     NO       S_ISFIFO
echo ./test | at now   /dev/tty   FAIL   NO       S_ISREG

Ubuntu Linux 11.04 시스템에서 다음 프로그램을 사용한 결과입니다.

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
int main() {
  char tty[L_ctermid+1];
  ctermid(tty);
  printf("ID: %s\n", tty);
  int fd = open(tty, O_RDONLY);
  if (fd < 0) perror("Could not open terminal");
  else {
    printf("Opened terminal\n");
    struct termios term;
    int r = tcgetattr(fd, &term);
    if (r < 0) perror("Could not get attributes");
    else printf("Got attributes\n");
  }
  if (isatty(fileno(stdin))) printf("Is a terminal\n");
  else printf("Is not a terminal\n");
  struct stat stats;
  int r = fstat(fileno(stdin), &stats);
  if (r < 0) perror("fstat failed");
  else {
    if (S_ISCHR(stats.st_mode)) printf("S_ISCHR\n");
    else if (S_ISFIFO(stats.st_mode)) printf("S_ISFIFO\n");
    else if (S_ISREG(stats.st_mode)) printf("S_ISREG\n");
    else printf("unknown stat mode\n");
  }
  return 0;
}

단말 장치

인터랙티브세션에 특정 기능이 필요한 경우 터미널 디바이스를 열고 (일시적으로) 를 사용하여 필요한 터미널 속성을 설정할 수 있습니다.tcsetattr().

Python의 예시

인터프리터가 인터프리터 실행 여부를 결정하는 Python 코드는isatty(). 기능PyRun_AnyFileExFlags()

/* Parse input from a file and execute it */

int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
                     PyCompilerFlags *flags)
{
    if (filename == NULL)
        filename = "???";
    if (Py_FdIsInteractive(fp, filename)) {
        int err = PyRun_InteractiveLoopFlags(fp, filename, flags);

Py_FdIsInteractive()

/*
 * The file descriptor fd is considered ``interactive'' if either
 *   a) isatty(fd) is TRUE, or
 *   b) the -i flag was given, and the filename associated with
 *      the descriptor is NULL or "<stdin>" or "???".
 */
int
Py_FdIsInteractive(FILE *fp, const char *filename)
{
    if (isatty((int)fileno(fp)))
        return 1;

호출하는 것isatty().

결론

인터랙티브의 정도는 다릅니다.확인용stdin파이프/파일 또는 실제 단말기에 연결되어 있습니다.isatty()자연스러운 방법이라고 생각합니다.

아마 다음과 같이 "stdin"이 fstat과 함께 있는 파일 형식을 체크하고 있을 것입니다.

struct stat stats;
fstat(0, &stats);
if (S_ISCHR(stats.st_mode)) {
    // Looks like a tty, so we're in interactive mode.
} else if (S_ISFIFO(stats.st_mode)) {
    // Looks like a pipe, so we're in non-interactive mode.
}

물론 Python은 오픈 소스이기 때문에 그들이 무엇을 하는지 보고 확실히 알 수 있습니다.

http://www.python.org/ftp/python/2.6.2/Python-2.6.2.tar.bz2

Windows 에서는, GetFileType 를 사용할 수 있습니다.

HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD type = GetFileType(hIn);
switch (type) {
case FILE_TYPE_CHAR: 
    // it's from a character device, almost certainly the console
case FILE_TYPE_DISK:
    // redirected from a file
case FILE_TYPE_PIPE:
    // piped from another program, a la "echo hello | myprog"
case FILE_TYPE_UNKNOWN:
    // this shouldn't be happening...
}

전화하시면 됩니다.stat(0, &result)확인하다!S_ISREG( result.st_mode )그건 Posix지 C/C++가 아니에요.

stat() 또는 fstat()을 호출하여 S_IFIFO가 st_mode로 설정되어 있는지 확인합니다.

언급URL : https://stackoverflow.com/questions/1312922/detect-if-stdin-is-a-terminal-or-pipe

반응형