Pokud máte zájem psát programování systému Linux, měli byste se naučit všechna základní volání knihoven/systémů. Tento článek obsahuje ukázkový program C, který pokrývá sadu systémových volání, která vám pomohou porozumět použití těchto základních volání knihoven.
Ukázkový kód C uvedený níže dělá následující:
- Automaticky otevře některé terminály
- Zobrazí zprávu, že relace běží jako uživatel root nebo bez uživatele root
- Zobrazte výše uvedenou zprávu na všech otevřených terminálech
Následuje 13 důležitých volání knihoven nebo systémových volání, která jsou zahrnuta v níže uvedeném příkladu kódu.
- memset() :Tato funkce vyplní prvních n bajtů oblasti paměti, na kterou ukazuje s, konstantním bajtem c.
- fopen() :Tato funkce otevře soubor, jehož název je řetězec, na který ukazuje jeho první argument, a přiřadí k němu proud.
- getcwd() :Tato funkce vrací řetězec zakončený nulou obsahující absolutní cestu, která je aktuálním pracovním adresářem volajícího procesu
- getuid() :Tato funkce vrací skutečné uživatelské ID volajícího procesu
- snprintf() :Tato funkce vytváří výstup podle formátu a zapisuje výstup do vyrovnávací paměti.
- fwrite() :Tato funkce se používá k zápisu dat do streamu
- fflush() :Tato funkce vynutí zápis všech dat uložených v uživatelském prostoru do konkrétního streamu
- fclose() :Tato funkce vyprázdní přidružený proud a zavře základní deskriptor souboru.
- system() :Tato funkce provede příkaz
- sleep() :Tato funkce uspí proces volání, dokud neuplynou zadané sekundy nebo dokud nepřijde signál, který není ignorován.
- opendir() :Tato funkce otevře adresářový proud
- readdir() :Tato funkce čte adresář, který je otevřen jako proud
- atoi() :Tato funkce převede argument ascii na celé číslo.
Následuje kód C, který ukazuje, jak používat všech výše uvedených 13 systémových volání.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<dirent.h>
#include<sys/types.h>
#include<pwd.h>
// A buffer to hold current working directory
char cwd[512];
void inform(char *path, char *binary_name)
{
// Declare variables for file operations
FILE *fp = NULL;
// A counter to be used in loop
unsigned int counter = 0;
// A buffer to hold the information message
char msg[1024];
// memset function initializes the bytes
// in the buffer 'msg' with NULL characters
memset(msg, '\0', sizeof(msg));
memset(cwd, '\0', sizeof(cwd));
// Check for the path to be non NULL
if(NULL== path)
{
printf("\n NULL path detected\n");
return;
}
// fopen will open the file represented
// by 'path' in read write mode.
fp = fopen(path,"r+");
if(!fp)
{
printf("\n Failed to open %s\n",path);
return;
}
else
{
printf("\n Successfully opened %s\n",path);
}
// getcwd() gives us the current working directory
// of the environemt from which this binary was
// executed
if(NULL == getcwd(cwd,sizeof(cwd)))
{
printf("\n Failed to get current directory\n");
return;
}
// getuid() returns the real user ID of the calling
// process.
// getuid() returns 0 for root and non zero for
// any other user.
if( 0 != getuid())
{
// This functions fills the buffer 'msg' with the formatted string by replacing %s in the harcoded string with the appropriate values
snprintf(msg,sizeof(msg),"\n\n\nYOU ARE NOT ROOT!!!!!");
}
else
{
snprintf(msg, sizeof(msg),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nYOU ARE ROOT!!!!!!!!!!!!!!");
}
// Make sure the information8 is printed 25 times on each
// open terminal
for(counter=0;counter<25;counter++)
{
printf("\n fwrite()\n");
// Write the information message on to the terminal
fwrite(msg, strlen(msg), 1, fp);
// Flush the message to the stdout of the terminal
fflush(fp);
// Wait for one second.
sleep(1);
}
// close the file representing the terminal
fclose(fp);
}
int main(int argc, char *argv[])
{
// Since we will do some directory operations
// So declare some variables for it.
DIR *dp = NULL;
struct dirent *ptr = NULL;
// This variable will contain the path to
// terminal
char *path = NULL;
// Used as a counter in loops
int i =0;
// Step1 :
// Open 5 terminals each after 2 seconds
// of delay.
for(;i<5;i++)
{
// The system API executes a shell command
// We try to execute two commands here
// Both of these commands will open up
// a terminal. We have used two commands
// just in case one of them fails.
system("gnome-terminal");
system("/usr/bin/xterm");
// This call is used to cause a delay in
// program execution. The argument to this
// function is the number of seconds for
// which the delay is required
sleep(2);
}
// Give user some 60 seconds before issuing
// a information message.
sleep(60);
// Now, open the directory /dev/pts which
// corresponds to the open command terminals.
dp = opendir("/dev/pts");
if(NULL == dp)
{
printf("\n Failed to open /dev/pts\n");
return 0;
}
// Now iterate over each element in the
// directory untill all the elements are
// iterated upon.
while ( NULL != (ptr = readdir(dp)) )
{
// ptr->d_name gives the current device
// name or the terminal name as a device.
// All the numeric names correspond to
// open terminals.
// To check the numeric values we use
// atoi().
// Function atoi() converts the ascii
// value into integer
switch(atoi(ptr->d_name))
{
// Initialize 'path' accordingly
case 0:path = "/dev/pts/0";
break;
case 1:
path = "/dev/pts/1";
break;
case 2:
path = "/dev/pts/2";
break;
case 3:
path = "/dev/pts/3";
break;
case 4:
path = "/dev/pts/4";
break;
case 5:
path = "/dev/pts/5";
break;
case 6:
path = "/dev/pts/6";
break;
case 7:
path = "/dev/pts/8";
break;
case 9:
path = "/dev/pts/9";
break;
default:
break;
}
if(path)
{
// Call this function to throw some information.
// Pass the path to terminal where the information
// is to be sent and the binary name of this
// program
inform(path, argv[0]);
// Before next iteration, make path point to
// NULL
path = NULL;
}
}
sleep(60);
return 0;
} Samotný výše uvedený kód je samovysvětlující, protože obsahuje adekvátní komentáře, které vysvětlují, co tato systémová volání dělají. Pokud jste nováčkem v programování systému Linux, tento kód dostatečně vysvětlí použití všech těchto důležitých funkcí. Pro více podrobností a pokročilé použití si prosím pozorně přečtěte jejich manuálové stránky.
Tento kód je simulací zábavného základního virového programu. Jakmile zkompilujete a spustíte výše uvedený program c, provede následující. Tento kód byl testován na Linux mint. Ale mělo by to fungovat na všech derivátech ubuntu.
- Uživatel uvidí 5 terminálů, které se otevírají jeden po druhém po 1 sekundě.
- Zatímco se uživatel bude divit, co se právě stalo, všechny jeho otevřené terminály začnou pomalu dostávat opakované informace o přihlášení, zda je přihlášení root nebo non-root.
- Upozorňujeme, že pro účely učení je v kódu povoleno protokolování ladění. Pokud se chcete pobavit, zakomentujte ladicí printf a poté jej spusťte.