tycommon: ensure common tools are running in terminology
This is done by reading the tertiary device attributes and expecting terminology's value.
This commit is contained in:
parent
a119ac10cc
commit
6b8da82722
|
@ -1,20 +1,117 @@
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "tycommon.h"
|
#include "tycommon.h"
|
||||||
|
|
||||||
|
/* returns 0 if running in terminology, something else otherwise */
|
||||||
int
|
int
|
||||||
is_running_in_terminology(void)
|
expect_running_in_terminology(void)
|
||||||
{
|
{
|
||||||
if (!getenv("TERMINOLOGY")) return 0;
|
char buf[32];
|
||||||
// Terminology's escape codes do not got through tmux
|
ssize_t len = 0;
|
||||||
if (getenv("TMUX")) return 0;
|
const char *expected = "\033P!|7E7E5459\033\\";
|
||||||
// Terminology's escape codes do not got through screen
|
const char *pos = expected;
|
||||||
if (getenv("STY")) return 0;
|
fd_set readset;
|
||||||
|
struct timeval tv;
|
||||||
|
struct termios ttystate, ttysave;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
return 1;
|
/* get current terminal state */
|
||||||
|
if (tcgetattr(STDIN_FILENO, &ttystate))
|
||||||
|
{
|
||||||
|
perror("tcgetattr");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ttysave = ttystate;
|
||||||
|
|
||||||
|
/* turn off canonical (buffered) mode and echo */
|
||||||
|
ttystate.c_lflag &= ~(ICANON | ECHO);
|
||||||
|
/* minimum of number input read: 1 byte. */
|
||||||
|
ttystate.c_cc[VMIN] = 1;
|
||||||
|
ttystate.c_cc[VTIME] = 0;
|
||||||
|
|
||||||
|
/* set new terminal attributes */
|
||||||
|
if (tcsetattr(STDIN_FILENO, TCSANOW, &ttystate))
|
||||||
|
{
|
||||||
|
perror("tcsetattr");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Query device attributes 3 */
|
||||||
|
buf[0] = '\033';
|
||||||
|
buf[1] = '[';
|
||||||
|
buf[2] = '=';
|
||||||
|
buf[3] = 'c';
|
||||||
|
len = ty_write(STDOUT_FILENO, buf, 4);
|
||||||
|
if (len != 4)
|
||||||
|
{
|
||||||
|
perror("write");
|
||||||
|
res = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos != (expected + strlen(expected)))
|
||||||
|
{
|
||||||
|
/* wait up to 1 second */
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
FD_ZERO(&readset);
|
||||||
|
FD_SET(STDIN_FILENO, &readset);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (select(1, &readset, NULL, NULL, &tv) < 0)
|
||||||
|
{
|
||||||
|
perror("select");
|
||||||
|
res = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(STDIN_FILENO, &readset))
|
||||||
|
{
|
||||||
|
len = read(STDIN_FILENO, buf, 1);
|
||||||
|
if (len != 1)
|
||||||
|
{
|
||||||
|
perror("read");
|
||||||
|
res = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf[0] == *pos)
|
||||||
|
pos++;
|
||||||
|
else if (pos == expected)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
/* restore attributes */
|
||||||
|
if (tcsetattr(STDIN_FILENO, TCSANOW, &ttysave))
|
||||||
|
{
|
||||||
|
perror("tcsetattr");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#ifndef _TY_COMMON_H__
|
#ifndef _TY_COMMON_H__
|
||||||
#define _TY_COMMON_H__ 1
|
#define _TY_COMMON_H__ 1
|
||||||
|
|
||||||
int is_running_in_terminology(void);
|
int expect_running_in_terminology(void);
|
||||||
ssize_t ty_write(int fd, const void *buf, size_t count);
|
ssize_t ty_write(int fd, const void *buf, size_t count);
|
||||||
|
|
||||||
#define ON_NOT_RUNNING_IN_TERMINOLOGY_EXIT_1() \
|
#define ON_NOT_RUNNING_IN_TERMINOLOGY_EXIT_1() \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
if (!is_running_in_terminology()) \
|
if (expect_running_in_terminology() != 0) \
|
||||||
{ \
|
{ \
|
||||||
fprintf(stderr, "not directly running in terminology\n"); \
|
fprintf(stderr, "not directly running in terminology\n"); \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
|
|
Loading…
Reference in New Issue