Když ls
Pokud se zavolá, vypíše všechny soubory/adresáře v aktuálním adresáři a pokusí se jich na každý řádek vejít co nejvíce. Proč je to tak, když je předán do wc -l
, vypíše počet souborů? Jak rozhodne, na kolika řádcích vypíše výsledky?
Přijatá odpověď:
Když ls
je spuštěn, analyzuje různé možnosti. Pomocí isatty() také zjišťuje, zda je výstup tty nebo ne.
ls.c:
kód
case LS_LS:
/* This is for the `ls' program. */
if (isatty (STDOUT_FILENO))
{
format = many_per_line;
/* See description of qmark_funny_chars, above. */
qmark_funny_chars = true;
}
else
{
format = one_per_line;
qmark_funny_chars = false;
}
break;
…
kód
/* disable -l */
if (format == long_format)
format = (isatty (STDOUT_FILENO) ? many_per_line : one_per_line);
atd.
Pokud chcete, můžete sestavit jednoduchý test:
isawhat.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
if (isatty(STDOUT_FILENO)) {
fprintf(stdout, "Word by word my world.n");
} else {
fprintf(stdout, "HELP! Stranger handling my words!!n");
}
fprintf(stderr, "Bye bye.n");
return 0;
}
Sestavil:
gcc -o isawhat isawhat.c
Pak např.:
$ ./isawhat | sed 's/word/world/'
Šířka se měří ve sloupcích. Jeden sloupec je jeden znak. Začíná to 80, pak zkontrolujte, zda je proměnná prostředí COLUMNS nastavena a obsahuje platný int, který není větší než SIZE_MAX (což je závislé na oblouku – váš terminál nikdy nebude tak široký (alespoň zatím)).
Zkuste např. echo $COLUMNS
. S největší pravděpodobností odráží počet sloupců, které máte v okně k dispozici. Při změně velikosti okna – toto se aktualizuje. Nejpravděpodobněji se také resetuje různými příkazy.
Jedním ze způsobů, jak to nastavit trochu obtížněji, je stty
. Např. stty columns 60
. Použijte stty -a
zobrazit všechny (man stty). Zábavný kus softwaru.
Pokud je v něm zkompilován také dotaz na sloupce pomocí ioctl(), zjistí velikost okna.. Předáním čísla souboru pro stdout do ioctl
a předání požadavku TIOCGWINSZ ve struktuře winsize
vyplňte počet sloupců.
To lze také demonstrovat jednoduchým c-kódem:
Zkompilujte, spusťte a změňte velikost okna. Mělo by se aktualizovat. Ctrl+C pro ukončení.
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <signal.h>
static int run;
void sig_handler(int sig) {
switch (sig) {
case SIGINT:
case SIGTERM:
case SIGSTOP:
run = 0;
break;
}
}
void sig_trap(int sig) {
if ((signal(sig, sig_handler)) == SIG_IGN)
signal(sig, SIG_IGN);
}
int main(void)
{
struct winsize ws;
sig_trap(SIGINT);
sig_trap(SIGTERM);
sig_trap(SIGSTOP);
run = 1;
while (run) {
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
fprintf(stdout, "r %s: %3d, %s: %dr",
"Columns", ws.ws_col,
"Rows", ws.ws_row
);
fflush(stdout);
}
usleep(5000);
}
fprintf(stdout, "n");
return 0;
}