爲了簡化Thomas Dickey's和Chris Dodd's答案,典型的碼要選擇哪個描述符被用來指終端是
int ttyfd;
/* Check standard error, output, and input, in that order. */
if (isatty(fileno(stderr)))
ttyfd = fileno(stderr);
else
if (isatty(fileno(stdout)))
ttyfd = fileno(stdout);
else
if (isatty(fileno(stdin)))
ttyfd = fileno(stdin);
else
ttyfd = -1; /* No terminal; redirecting to/from files. */
如果您的應用程序堅持要訪問控制終端(用戶用來執行此過程的終端),如果有的話,您可以使用以下new_terminal_descriptor()
函數。爲簡單起見,我將在一個示例程序中嵌入它:
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int new_terminal_descriptor(void)
{
/* Technically, the size of this buffer should be
* MAX(L_ctermid + 1, sysconf(_SC_TTY_NAME_MAX))
* but 256 is a safe size in practice. */
char buffer[256], *path;
int fd;
if (isatty(fileno(stderr)))
if (!ttyname_r(fileno(stderr), buffer, sizeof buffer)) {
do {
fd = open(path, O_RDWR | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd != -1)
return fd;
}
if (isatty(fileno(stdout)))
if (!ttyname_r(fileno(stdout), buffer, sizeof buffer)) {
do {
fd = open(path, O_RDWR | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd != -1)
return fd;
}
if (isatty(fileno(stdin)))
if (!ttyname_r(fileno(stdin), buffer, sizeof buffer)) {
do {
fd = open(path, O_RDWR | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd != -1)
return fd;
}
buffer[0] = '\0';
path = ctermid(buffer);
if (path && *path) {
do {
fd = open(path, O_RDWR | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd != -1)
return fd;
}
/* No terminal. */
errno = ENOTTY;
return -1;
}
static void wrstr(const int fd, const char *const msg)
{
const char *p = msg;
const char *const q = msg + ((msg) ? strlen(msg) : 0);
while (p < q) {
ssize_t n = write(fd, p, (size_t)(q - p));
if (n > (ssize_t)0)
p += n;
else
if (n != (ssize_t)-1)
return;
else
if (errno != EINTR)
return;
}
}
int main(void)
{
int ttyfd;
ttyfd = new_terminal_descriptor();
if (ttyfd == -1)
return EXIT_FAILURE;
/* Let's close the standard streams,
* just to show we're not using them
* for anything anymore. */
fclose(stdin);
fclose(stdout);
fclose(stderr);
/* Print a hello message directly to the terminal. */
wrstr(ttyfd, "\033[1;32mHello!\033[0m\n");
return EXIT_SUCCESS;
}
的wrstr()
功能只是一個輔助功能,可以立即將指定的字符串寫入指定的文件描述符,無需緩衝。該字符串包含ANSI顏色代碼,因此,如果成功,即使標準流已關閉,它也會向終端打印淺綠色Hello!
。
如果將上面的內容保存爲example.c
,則可以使用例如,
gcc -Wall -Wextra -O2 example.c -o example
,並使用
./example
因爲new_terminal_descriptor()
使用ctermid()
函數來獲取名稱(路徑)來控制終端作爲最後的手段來看 - 這是不常見的,但我想表現在這裏很容易,如果你決定有必要做的事 - ,將打印hello消息到終端,甚至在所有數據流都被重定向:
./example </dev/null >/dev/null 2>/dev/null
最後,如果你想知道,沒有一個是「特殊」的。我不是在談論控制檯終端,這是許多Linux發行版提供的基於文本的控制檯界面,作爲圖形環境的替代選擇,也是大多數Linux服務器提供的唯一本地界面。以上所有使用的只是普通的POSIX僞終端接口,並且可以很好地工作。 xterm
或任何其他普通終端仿真器(或Linux控制檯),在所有POSIXy系統 - Linux,Mac OS X和BSD變體中。
fd表示文件描述符 – HoKy22
@ HoKy22謝謝,'fd'的兩個選項,即'stdin'和'stdout'都是文件描述符,因此它不是很清楚,我需要詢問 – humanityANDpeace