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.