Cap. 12. Programare

# Cap. 12. Programare

Vă ofer câteva sfaturi pentru cei care doresc să învețe programarea pe sistemul Debian la un nivel suficient pentru a putea urmări codul sursă al pachetelor. Iată câteva pachete importante și documentația aferentă pentru programare.

Referințele sunt disponibile introducând „`man nume`” după instalarea pachetelor `manpages` și `manpages-dev`. Referințele pentru instrumentele GNU sunt disponibile prin tastarea „`info nume_program`” după instalarea pachetelor de documentație relevante. Este posibil să fie necesar să includeți arhivele `contrib` și `non-free` în plus față de arhiva `main`, deoarece unele documentații GFDL nu sunt considerate conforme cu DFSG.

Vă recomandăm să utilizați instrumentele sistemului de control al versiunilor. Consultați Secțiune 10.5, „Git”.

| Avertisment
Nu folosiți „`test`” ca nume pentru un fișier executabil de testare. „`test`” este o comandă internă a shell-ului.

| Atenție
Ar trebui să instalați programele software compilate direct din sursă în „`/usr/local`” sau „`/opt`” pentru a evita suprapunerea cu programele din sistem.

| Indicație
Exemplele de cod pentru crearea melodiei „99 Bottles of Beer” ar trebui să vă ofere idei utile pentru aproape toate limbajele de programare.

## 12.1. Scriptul Shell

Scriptul shell este un fișier text cu dreptul de execuție activat și conține comenzi în următorul format.

    #!/bin/sh
     ... command lines

Prima linie specifică interpretul shell care citește și execută conținutul acestui fișier.

Citirea scripturilor shell este cea mai bună modalitate de a înțelege cum funcționează un sistem de tip Unix. Aici vă ofer câteva indicații și sfaturi utile pentru programarea în shell. Consultați „Greșeli în shell” (https://www.greenend.org.uk/rjk/2001/04/shell.html) pentru a învăța din greșeli.

Spre deosebire de modul interactiv al shell-ului (a se vedea Secțiune 1.5, „Comanda simplă de shell” și Secțiune 1.6, „Procesarea textului în stilul Unix”), scripturile shell utilizează frecvent parametri, condiții și bucle.

### 12.1.1. Compatibilitate cu shell-ul POSIX

Multe scripturi de sistem pot fi interpretate de oricare dintre shell-urile POSIX (vedeți Tabel 1.13, „Lista programelor shell”).

- Shell-ul POSIX implicit, neinteractiv, „`/usr/bin/sh`”, este o legătură simbolică care indică spre `/usr/bin/dash` și este utilizat de multe programe din sistem.

- Shell-ul POSIX interactiv implicit este `/usr/bin/bash`.

Evitați să scrieți un script de shell care conține „bashisme” (particularități ale shell-ului bash) sau „zshisme>” (particularități ale shell-ului zsh), pentru a-l face compatibil cu toate shell-urile POSIX. Puteți verifica acest lucru folosind checkbashisms(1).

Tabel 12.1. Lista expresiilor tipice din Bash („bashisme”)

Bine: POSIX | De evitat: „bashismul”
--- | ---
`if [ "$foo" = "$bar" ] ; then …` | `if [ "$foo" == "$bar" ] ; then …`
`diff -u file.c.orig file.c` | `diff -u file.c{.orig,}`
`mkdir /foobar /foobaz` | `mkdir /foo{bar,baz}`
`funcname() { … }` | `function funcname() { … }`
format octal: "`\377`" | format hexazecimal: "`\xff`"

Comanda „`echo`” trebuie utilizată cu următoarele precauții, deoarece implementarea sa diferă între comenzile interne ale shell-ului și cele externe.

- Evitați utilizarea oricăror opțiuni ale comenzii «echo» cu excepția „`-n`”.

- Evitați utilizarea secvențelor de eludare în șir, deoarece gestionarea acestora variază.

| Notă
Deși opțiunea „`-n`” nu este, de fapt, o sintaxă POSIX, ea este acceptată în general.

| Indicație
Folosiți comanda „`printf`” în locul comenzii „`echo`” dacă trebuie să includeți secvențe de eludare în șirul de ieșire.

### 12.1.2. Parametri shell

În scripturile shell se utilizează frecvent parametri speciali ai shell-ului.

Tabel 12.2. Lista parametrilor shell-ului

prametru shell | valoare
--- | ---
`$0` | numele shell-ului sau al scriptului shell
`$1` | primul (1) argument al shell-ului
`$9` | al nouălea (9-lea) argument al shell-ului
`$#` | numărul parametrilor de poziție
`"$*"` | `"$1 $2 $3 $4 … "`
`"$@"` | `"$1" "$2" "$3" "$4" …`
`$?` | starea de ieșire a celei mai recente comenzi
`$$` | PID-ul acestui script de shell
`$!` | PID-ul celei mai recente sarcini de fundal pornite

Expansiunile parametrilor de bază pe care trebuie să le rețineți sunt următoarele.

Tabel 12.3. Lista expansiunilor parametrilor shell-ului

forma expresiei parametrului | valoarea dacă `var` este definită | valoarea dacă `var` nu este definită
--- | --- | ---
`${var:-string}` | "`$var`" | „`șir`”
`${var:+string}` | „`șir`” | „`null`”
`${var:=string}` | "`$var`" | „`șir`” (și execută „`var=șir`”)
`${var:?string}` | "`$var`" | afișează „`șir`ul” la stderr (și iese cu eroare)

Aici, caracterul „`:`” din toți acești operatori este, de fapt, opțional.

- cu „`:`” operatorul = verifică dacă există și nu este nul

- fără „`:`” operatorul = verifică doar dacă există

Tabel 12.4. Lista substituțiilor parametrilor cheie ai shell-ului

forma de substituire a parametrilor | rezultatul
--- | ---
`${var%suffix}` | elimină cel mai mic model de sufix
`${var%%suffix}` | elimină cel mai mare model de sufix
`${var#prefix}` | elimină cel mai mic model de prefix
`${var##prefix}` | elimină cel mai mare model de prefix

### 12.1.3. Condiționale shell

Fiecare comandă returnează un cod de ieșire care poate fi utilizat în expresii condiționale.

- Succes: 0 („True” - adevărat)

- Eroare: diferit de 0 („False” - fals)

| Notă
În contextul condițional al shell-ului, „0” înseamnă „Adevărat”, în timp ce în contextul condițional al limbajului C, „0” înseamnă „Fals”.

| Notă
„`[`” este echivalentul comenzii `test`, care evaluează argumentele sale până la „`]`” ca o expresie condițională.

Expresiile condiționale de bază pe care trebuie să le rețineți sunt următoarele.

- „`comandă && dacă_succes_execută_și_această_comandă || true`”

- „`comandă || dacă_nu_a_reușit_execută_și_această_comandă || true`”

- Un fragment de cod cu mai multe linii, ca în exemplul următor

    if [ conditional_expression ]; then
     if_success_run_this_command
    else
     if_not_success_run_this_command
    fi

Aici a fost necesară adăugarea secvenței „`|| true`” pentru a se asigura că acest script de shell nu se închide accidental la această linie atunci când shell-ul este invocat cu opțiunea „`-e`”.

Tabel 12.5. Lista operatorilor de comparare a fișierelor în expresia condițională

ecuație | condiție care returnează valoarea logică „adevărat”
--- | ---
`-e fișier` | fișierul există
`-d fișier` | fișierul există și este un director
`-f fișier` | fișierul există și este un fișier obișnuit
`-w fișier` | fișierul există și poate fi accesat pentru scriere
`-x fișier` | fișierul există și este executabil
`fișier1 -nt fișier2` | fișier1 este mai recent decât fișier2 (data modificării)
`fișier1 -ot fișier2` | fișier1 este mai vechi decât fișier2 (data modificării)
`fișier1 -ef fișier2` | fișier1 și fișier2 se află pe același dispozitiv și au același număr de nod-i

Tabel 12.6. Lista operatorilor de comparare a șirurilor în expresia condițională

ecuație | condiție care returnează valoarea logică „adevărat”
--- | ---
`-z șir` | lungimea șirului este zero
`-n șir` | lungimea șirului este diferită de zero
`șir1 = șir2` | șirul1 și șirul2 sunt egale
`șir1 != șir2` | șirul1 și șirul2 nu sunt egale
`șir1 < șir2` | șirul1 este sortat înaintea șirului2 (în funcție de configurația regională)
`șir1 > șir2` | șirul1 este sortat după șirul2 (în funcție de configurația regională)

Operatorii aritmetici de comparare a numerelor întregi din expresia condițională sunt „`-eq`”, „`-ne`”, „`-lt`„, ”`-le`„, ”`-gt`„ și ”`-ge`".

### 12.1.4. Bucle shell

În shell-ul POSIX există mai multe expresii de tip buclă care pot fi utilizate.

- „`for x in foo1 foo2 … ; do comanda ; done`” efectuează o buclă prin atribuirea elementelor din lista „`foo1 foo2 …`” variabilei „`x`” și executarea „`comenzii`”.

- „`while condiție ; do comanda ; done`” repetă „`comanda`” atâta timp cât „`condiția`” este adevărată.

- „`until condiție ; do comanda ; done`” repetă „`comanda`” atâta timp cât „`condiția`” nu este adevărată.

- „`break`” permite ieșirea din buclă.

- „`continue`” permite reluarea următoarei iterații a buclei.

| Indicație
Iterarea numerică specifică limbajului C poate fi realizată folosind seq(1) ca generator de tipul „`foo1 foo2 …`”.

| Indicație
Consultați Secțiune 9.4.9, „Repetarea unei comenzi care parcurge fișierele”.

### 12.1.5. Variabilele de mediu ale shell

Este posibil ca unele variabile de mediu uzuale pentru linia de comandă a shell-ului standard să nu fie disponibile în mediul de execuție al scriptului dumneavoastră.

- Pentru „`$USER`”, folosiți „`$(id -un)`”

- Pentru „`$UID`”, folosiți „`$(id -u)`”

- Pentru „`$HOME`”, folosiți „`$(getent passwd „$(id -u)”|cut -d „:” -f 6)`” (această comandă funcționează, de asemenea, pe Secțiune 4.5.2, „Sistemul modern de gestionare centralizată”)

### 12.1.6. Secvența de procesare a liniei de comandă shell

Shell-ul procesează un script aproximativ după următoarea secvență.

- Shell-ul citește o linie.

- Shell-ul grupează o parte a liniei ca un singur element (token) dacă aceasta se află între `"…"` sau `'…'`.

- Shell-ul împarte restul unei linii în elemente (token-uri) după cum urmează.

  - Spații-albe: `spațiu tabulator linie-nouă`

  - Metacaractere::`< > | ; & ( )`

- Shell-ul verifică cuvântul rezervat pentru fiecare token, pentru a-și adapta comportamentul în cazul în care acesta nu se află între `"…"` sau `'…'`.

  - cuvânt rezervat: `if then elif else fi for in while unless do done case esac`

- Shell-ul extinde alias dacă acesta nu se află între `"…"` sau `'…'`.

- Shell-ul expandează tilde dacă nu se află între `"…"` sau `'…'`.

  - „`~`” → directorul personal al utilizatorului curent

  - „`~utilizator`” → directorul personal al `utilizatorului`

- Shell-ul înlocuiește parametrul cu valoarea acestuia, dacă nu se află între `'…'`.

  - parametru: „`$PARAMETER`” sau „`${PARAMETER}`”

- Shell-ul extinde substituirea comenzii dacă aceasta nu se află între `'…'`.

  - „`$( comandă )`” → ieșirea comenzii „`comandă`”

  - „`` comandă ``” → rezultatul comenzii „`comandă`”

- Shell-ul extinde expresia de tip glob (cu caractere joker) pentru ruta la numele de fișiere corespunzătoare, dacă acestea nu se află între `"…"` sau `'…'`.

  - `*` → orice caractere

  - `?` → un caracter

  - `[…]` → oricare dintre caracterele din "`…`"

- Shell-ul caută comanda din următoarele și o execută.

  - definiția funcției

  - comanda internă

  - fișierul executabil din „`$PATH`”

- Shell-ul trece la linia următoare și repetă acest proces de la începutul secvenței.

Ghilimelele simple între ghilimele duble nu au niciun efect.

Executarea comenzii „`set -x`” în shell sau lansarea shell-ului cu opțiunea „`-x`” determină shell-ul să afișeze toate comenzile executate. Acest lucru este foarte util pentru depanare.

### 12.1.7. Programe utile pentru scripturile shell

Pentru a face programul dvs. de tip shell cât mai portabil posibil pe sistemele Debian, este recomandat să limitați utilizarea programelor utilitare la cele furnizate de pachetele esențiale.

- «`aptitude search ~E`» listează pachetele esențiale.

- «`dpkg -L nume_pachet | grep '/man/man.*/'`» afișează paginile de manual pentru comenzile oferite de pachetul `nume_pachet`.

Tabel 12.7. Lista pachetelor care conțin mici programe utilitare pentru scripturi shell

pachet | popcon(popularitate) | dimensiune | descriere
--- | --- | --- | ---
`dash` | V:928, I:998 | 207 | un shell mic și rapid, compatibil cu POSIX, pentru `sh`
`coreutils` | V:910, I:1000 | 17994 | instrumente de bază GNU
`grep` | V:779, I:1000 | 1297 | GNU `grep`, `egrep` și `fgrep`
`sed` | V:762, I:1000 | 987 | GNU `sed`
`mawk` | V:485, I:998 | 295 | mic și rapid `awk`
`debianutils` | V:936, I:997 | 225 | diverse instrumente specifice Debian
`bsdutils` | V:445, I:1000 | 338 | instrumente de bază din 4.4BSD-Lite
`bsdextrautils` | V:754, I:863 | 382 | instrumente extra din 4.4BSD-Lite
`moreutils` | V:18, I:39 | 232 | instrumente Unix suplimentare

| Indicație
Deși `moreutils` s-ar putea să nu existe în afara distribuției Debian, acesta oferă câteva programe mici și interesante. Cel mai notabil dintre acestea este sponge(8), care se dovedește destul de util atunci când doriți să suprascrieți un fișier original.

Consultați Secțiune 1.6, „Procesarea textului în stilul Unix” pentru exemple.

## 12.2. Programarea în limbaje interpretate

Tabel 12.8. Lista pachetelor legate de interpret

pachet | popcon(popularitate) | dimensiune | documentație
--- | --- | --- | ---
`dash` | V:928, I:998 | 207 | sh: un shell mic și rapid, compatibil cu POSIX, pentru `sh`
`bash` | V:893, I:1000 | 7309 | sh: „`info bash`” furnizat de `bash-doc`
`mawk` | V:485, I:998 | 295 | AWK: o versiune compactă și rapidă a `awk`
`gawk` | V:250, I:301 | 3289 | AWK: „`info gawk`” furnizat de `gawk-doc`
`perl` | V:673, I:992 | 836 | Perl: perl(1) și paginile HTML furnizate de `perl-doc` și `perl-doc-html`
`libterm-readline-gnu-perl` | V:2, I:27 | 439 | Extensie Perl pentru biblioteca GNU ReadLine/History: perlsh(1)
`libreply-perl` | V:0.01, I:0.10 | 171 | REPL pentru Perl: reply(1)
`libdevel-repl-perl` | V:0.03, I:0.57 | 237 | REPL pentru Perl: re.pl(1)
`python3` | V:717, I:974 | 80 | Python: python3(1) și paginile HTML furnizate de `python3-doc`
`tcl` | V:23, I:176 | 20 | Tcl: tcl(3) și paginile de manual detaliate furnizate de `tcl-doc`
`tk` | V:17, I:169 | 20 | Tk: tk(3) și paginile de manual detaliate furnizate de `tk-doc`
`ruby` | V:71, I:157 | 32 | Ruby: ruby(1), erb(1), irb(1), rdoc(1), ri(1)

Când doriți să automatizați o sarcină în Debian, ar trebui să o programați mai întâi într-un limbaj interpretat. Ghidul pentru alegerea limbajului interpretat este:

- Folosiți `dash` dacă sarcina este una simplă, care combină programe CLI cu un program shell.

- Folosiți `python3` dacă sarcina nu este una simplă și o scrieți de la zero.

- Folosiți `perl`, `tcl`, `ruby`, ... dacă există un cod existent în Debian care utilizează unul dintre aceste limbaje și care trebuie modificat pentru a îndeplini sarcina.

Dacă codul rezultat este prea lent, puteți rescrie doar porțiunea esențială pentru viteza de execuție într-un limbaj compilat și o puteți apela din limbajul interpretat.

### 12.2.1. Depanarea codurilor în limbaje interpretate

Majoritatea interpreților oferă funcționalități de bază pentru verificarea sintaxei și urmărirea codului.

- «dash -n script.sh» - Verificarea sintaxei unui script Shell

- «dash -x script.sh» - Trasarea execuției unui script Shell

- «python -m py_compile script.py» - Verificarea sintaxei unui script Python

- «python -mtrace --trace script.py» - Trasarea execuției unui script Python

- “perl -I ../libpath -c script.pl” - Verificarea sintaxei unui script Perl

- “perl -d:Trace script.pl” - Trasarea execuției unui script Perl

Pentru a testa codul pentru `dash`, încercați Secțiune 9.1.4, „Readline wrapper (învăluitorul «readline»)”, care oferă un mediu interactiv similar cu `bash`.

Pentru a testa codul în `Perl`, încercați mediul REPL pentru Perl, care oferă un mediu de tip Python – adică un mediu REPL (=READ + EVAL + PRINT + LOOP) pentru Perl.

### 12.2.2. Program cu interfață grafică (GUI) și script de shell

Scriptul Shell poate fi îmbunătățit pentru a crea un program cu interfață grafică atractivă. Secretul constă în utilizarea unuia dintre așa-numitele programe de tip dialog, în locul interacțiunii monotone bazate pe comenzile `echo` și `read`.

Tabel 12.9. Lista programelor de dialog

pachet | popcon(popularitate) | dimensiune | descriere
--- | --- | --- | ---
`x11-utils` | V:222, I:551 | 651 | xmessage(1): afișează un mesaj sau o solicitare într-o fereastră (X)
`whiptail` | V:303, I:997 | 61 | afișează casete de dialog ușor de utilizat din scripturi shell (newt)
`dialog` | V:8, I:77 | 520 | afișează casete de dialog ușor de utilizat din scripturi shell (ncurses)
`zenity` | V:74, I:338 | 193 | afișează casete de dialog grafice din scripturi shell (GTK)
`ssft` | V:0.01, I:0.16 | 80 | Instrument de interfață pentru scripturi Shell (înveliș pentru zenity, kdialog și dialog cu gettext)
`gettext` | V:51, I:216 | 20468 | "`/usr/bin/gettext.sh`": traduce mesajul

Iată un exemplu de program cu interfață grafică care demonstrează cât de ușor este să realizezi acest lucru folosind doar un script de shell.

Acest script utilizează `zenity` pentru a selecta un fișier (implicit `/etc/motd`) și a-l afișa.

Lansatorul GUI pentru acest script poate fi creat urmând instrucțiunile de la Secțiune 9.4.10, „Pornirea unui program din interfața grafică”.

    #!/bin/sh -e
    # Copyright (C) 2021 Osamu Aoki <osamu@debian.org>, Public Domain
    # vim:set sw=2 sts=2 et:
    DATA_FILE=$(zenity --file-selection --filename="/etc/motd" --title="Select a file to check") || \
      ( echo "E: File selection error" >&2 ; exit 1 )
    # Check size of archive
    if ( file -ib "$DATA_FILE" | grep -qe '^text/' ) ; then
      zenity --info --title="Check file: $DATA_FILE" --width 640  --height 400 \
        --text="$(head -n 20 "$DATA_FILE")"
    else
      zenity --info --title="Check file: $DATA_FILE" --width 640  --height 400 \
        --text="The data is MIME=$(file -ib "$DATA_FILE")"
    fi

Acest tip de abordare a programelor cu interfață grafică (GUI) folosind scripturi shell este utilă doar în cazurile simple. Dacă intenționați să scrieți un program mai complex, vă recomandăm să îl scrieți pe o platformă mai performantă.

### 12.2.3. Acțiuni personalizate pentru gestionarul de fișiere cu interfață grafică

Programele de gestionare a fișierelor cu interfață grafică pot fi extinse pentru a efectua anumite operații uzuale asupra fișierelor selectate, folosind pachete de extensii suplimentare. De asemenea, pot fi configurate să execute operații personalizate foarte specifice prin adăugarea propriilor scripturi.

- Pentru GNOME, consultați NautilusScriptsHowto.

- Pentru KDE, consultați Creating Dolphin Service Menus (Crearea meniurilor de servicii Dolphin).

- Pentru Xfce, consultați Thunar - Custom Actions (Thunar - Acțiuni personalizate) și https://help.ubuntu.com/community/ThunarCustomActions.

- Pentru LXDE, consultați Custom Actions (Acțiuni personalizate).

### 12.2.4. Nebunia scripturilor scurte în Perl

Pentru a procesa datele, `sh` trebuie să lanseze subprocese care execută `cut`, `grep`, `sed` etc., iar acest lucru este lent. Pe de altă parte, `perl` dispune de capacități interne de procesare a datelor și este rapid. De aceea, multe scripturi de întreținere a sistemului pe Debian folosesc `perl`.

Să analizăm următorul fragment de script AWK de o singură linie și echivalentele sale în Perl.

    awk '($2=="1957") { print $3 }' |

Aceasta este echivalentă cu oricare dintre următoarele linii.

    perl -ne '@f=split; if ($f[1] eq "1957") { print "$f[2]\n"}' |

    perl -ne 'if ((@f=split)[1] eq "1957") { print "$f[2]\n"}' |

    perl -ne '@f=split; print $f[2] if ( $f[1]==1957 )' |

    perl -lane 'print $F[2] if $F[1] eq "1957"' |

    perl -lane 'print$F[2]if$F[1]eq+1957' |

Ultima este o ghicitoare. Aceasta a folosit următoarele caracteristici ale limbajului Perl.

- Spațiul în alb este opțional.

- Există o conversie automată de la număr la șir de caractere.

- Trucuri pentru executarea Perl prin opțiuni de linie de comandă: perlrun(1)

- Variabile speciale Perl: perlvar(1)

Această flexibilitate este punctul forte al limbajului Perl. În același timp, aceasta ne permite să creăm coduri criptice și încâlcite. Așadar, fiți atenți.

## 12.3. Programarea în limbaje compilate

Tabel 12.10. Lista pachetelor legate de compilator

pachet | popcon(popularitate) | dimensiune | descriere
--- | --- | --- | ---
`gcc` | V:155, I:564 | 36 | compilatorul GNU C
`libc6-dev` | V:269, I:584 | 12861 | biblioteca GNU C: biblioteci de dezvoltare și fișiere de antet
`g++` | V:57, I:531 | 13 | compilatorul GNU C++
`libstdc++-16-dev` | V:0.7, I:4.3 | 24382 | biblioteca standard GNU C++ v3 (fișiere de dezvoltare)
`cpp` | V:332, I:719 | 18 | preprocesorul GNU C
`gettext` | V:51, I:216 | 20468 | instrumente de internaționalizare GNU
`glade` | V:0.7, I:2.7 | 1613 | constructor de interfețe grafice de utilizator GTK
`valac` | V:0.2, I:3.2 | 533 | limbaj similar cu C# pentru sistemul GObject
`flex` | V:7, I:68 | 1247 | generator de analizare lexicală rapidă compatibil cu LEX-
`bison` | V:7, I:73 | 3122 | generator de analizare compatibil cu YACC
`susv2` | I:0.03 | 16 | preia „Specificațiile UNIX unice v2”
`susv3` | I:0.06 | 16 | preia „Specificațiile UNIX unice v3”
`susv4` | I:0.04 | 16 | preia „Specificațiile UNIX unice v4”
`golang` | I:22 | 12 | compilator pentru limbajul de programare Go
`rustc` | V:5, I:20 | 13061 | limbajul de programare de sisteme Rust
`gfortran` | V:4, I:50 | 15 | compilatorul GNU Fortran 95
`fpc` | I:2.3 | 101 | Free Pascal

Aici, Secțiune 12.3.3, „Flex — o versiune îmbunătățită a Lex” și Secțiune 12.3.4, „Bison — o versiune îmbunătățită a Yacc” sunt incluse pentru a arăta cum se pot scrie programe de tip compilator în limbajul C, prin compilarea unei descrieri de nivel superior în limbajul C.

### 12.3.1. C

Puteți configura mediul necesar pentru a compila programe scrise în limbajul de programare C urmând pașii de mai jos.

    # apt-get install glibc-doc manpages-dev libc6-dev gcc build-essential

Pachetul `libc6-dev`, adică biblioteca GNU C, oferă biblioteca standard C, care este o colecție de fișiere antet și rutine de bibliotecă utilizate de limbajul de programare C.

A se vedea următoarele referințe pentru limbajul C.

- „`info libc`” (referința funcțiilor bibliotecii C)

- gcc(1) și «`info gcc`»

- each_C_library_function_name(3)

- Kernighan & Ritchie, „The C Programming Language” - Limbajul de programare C, ediția a II-a (Prentice Hall)

### 12.3.2. Program simplu în limbajul C (gcc)

Un exemplu simplu, „`example.c`”, poate fi compilat împreună cu biblioteca „`libm`” într-un fișier executabil „`run_example`” după cum urmează.

    $ cat > example.c << EOF
    #include <stdio.h>
    #include <math.h>
    #include <string.h>

    int main(int argc, char **argv, char **envp){
            double x;
            char y[11];
            x=sqrt(argc+7.5);
            strncpy(y, argv[0], 10); /* prevent buffer overflow */
            y[10] = '\0'; /* fill to make sure string ends with '\0' */
            printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]);
            return 0;
    }
    EOF
    $ gcc -Wall -g -o run_example example.c -lm
    $ ./run_example
            1, 2.915, ./run_exam,     (null)
    $ ./run_example 1234567890qwerty
            2, 3.082, ./run_exam, 1234567890qwerty

Aici, „`-lm`” este necesar pentru a lega biblioteca „`/usr/lib/libm.so`” din pachetul `libc6` pentru sqrt(3). Biblioteca propriu-zisă se află în „`/lib/`” cu numele de fișier „`libm.so.6`”, care este o legătură simbolică către „`libm-2.7.so`”.

Uită-te la ultimul parametru din textul afișat. Are mai mult de 10 caractere, deși s-au specificat „`%10s`”.

Utilizarea funcțiilor de operare cu memoria prin intermediul indicatoare fără verificări de limite, precum sprintf(3) și strcpy(3), este învechită pentru a preveni exploatările de tip „buffer overflow” (debordare a memoriei tampon) care profită de efectele de depășire menționate mai sus. În schimb, utilizați snprintf(3) și strncpy(3).

### 12.3.3. Flex — o versiune îmbunătățită a Lex

Flex este un generator de analizare lexicală rapidă, compatibil cu Lex.

Tutorialul pentru flex(1) poate fi găsit în «`info flex`».

Multe exemple simple pot fi găsite în „`/usr/share/doc/flex/examples/`”. [7]

### 12.3.4. Bison — o versiune îmbunătățită a Yacc

În Debian, există mai multe pachete care oferă un generator de analizare LR cu citire anticipată compatibil cu Yacc sau un generator de analizare LALR.

Tabel 12.11. Lista generatoarelor de analizare LALR compatibile cu Yacc

pachet | popcon(popularitate) | dimensiune | descriere
--- | --- | --- | ---
`bison` | V:7, I:73 | 3122 | generator de analizare LALR GNU
`byacc` | V:0.1, I:3.0 | 263 | generator de analizare LALR Berkeley
`btyacc` | V:0.01, I:0.06 | 247 | generator de analizare cu capacitate de urmărire bazat pe `byacc`

Tutorialul pentru bison(1) poate fi găsit în «`info bison`».

Trebuie să furnizați propriile funcții „`main()`” și „`yyerror()`”. Funcția „`main()`” apelează funcția „`yyparse()`”, care la rândul ei apelează funcția „`yylex()`”, create de obicei cu ajutorul Flex.

Iată un exemplu de creare a unui program simplu de calculator pentru terminal.

Să creăm `example.y`:

    /* calculator source for bison */
    %{
    #include <stdio.h>
    extern int yylex(void);
    extern int yyerror(char *);
    %}

    /* declare tokens */
    %token NUMBER
    %token OP_ADD OP_SUB OP_MUL OP_RGT OP_LFT OP_EQU

    %%
    calc:
     | calc exp OP_EQU    { printf("Y: RESULT = %d\n", $2); }
     ;

    exp: factor
     | exp OP_ADD factor  { $$ = $1 + $3; }
     | exp OP_SUB factor  { $$ = $1 - $3; }
     ;

    factor: term
     | factor OP_MUL term { $$ = $1 * $3; }
     ;

    term: NUMBER
     | OP_LFT exp OP_RGT  { $$ = $2; }
      ;
    %%

    int main(int argc, char **argv)
    {
      yyparse();
    }

    int yyerror(char *s)
    {
      fprintf(stderr, "error: '%s'\n", s);
    }

Să creăm `example.l`:

    /* calculator source for flex */
    %{
    #include "example.tab.h"
    %}

    %%
    [0-9]+ { printf("L: NUMBER = %s\n", yytext); yylval = atoi(yytext); return NUMBER; }
    "+"    { printf("L: OP_ADD\n"); return OP_ADD; }
    "-"    { printf("L: OP_SUB\n"); return OP_SUB; }
    "*"    { printf("L: OP_MUL\n"); return OP_MUL; }
    "("    { printf("L: OP_LFT\n"); return OP_LFT; }
    ")"    { printf("L: OP_RGT\n"); return OP_RGT; }
    "="    { printf("L: OP_EQU\n"); return OP_EQU; }
    "exit" { printf("L: exit\n");   return YYEOF; } /* YYEOF = 0 */
    .      { /* ignore all other */ }
    %%

Apoi, pentru a încerca acest lucru, executați următoarea comandă din linia de comandă:

    $ bison -d example.y
    $ flex example.l
    $ gcc -lfl example.tab.c lex.yy.c -o example
    $ ./example
    1 + 2 * ( 3 + 1 ) =
    L: NUMBER = 1
    L: OP_ADD
    L: NUMBER = 2
    L: OP_MUL
    L: OP_LFT
    L: NUMBER = 3
    L: OP_ADD
    L: NUMBER = 1
    L: OP_RGT
    L: OP_EQU
    Y: RESULT = 9

    exit
    L: exit

## 12.4. Instrumente de analiză statică a codului

Instrumentele de tip Lint pot facilita efectuarea automată a analizei statice a codului.

Instrumentele de tip Indent pot facilita revizuirea manuală a codului prin reformatarea consecventă a codurilor sursă.

Instrumentele precum Ctags pot ajuta la revizuirea manuală a codului prin generarea unui fișier index (sau de etichete) cu numele identificate în codurile sursă.

| Indicație
Configurarea editorului preferat (`emacs` sau `vim`) pentru a utiliza module de motoare de verificare sintactică (lint) asincrone vă ajută la scrierea codului. Aceste module devin din ce în ce mai performante, profitând de Language Server Protocol. Având în vedere că evoluează rapid, utilizarea codului lor din sursa originală, în locul pachetului Debian, poate fi o opțiune bună.

Tabel 12.12. Lista instrumentelor pentru analiza statică a codului

pachet | popcon(popularitate) | dimensiune | descriere
--- | --- | --- | ---
`vim-ale` | I:0.80 | 2833 | motor lint asincron pentru Vim 8 și NeoVim
`vim-syntastic` | I:2.0 | 1379 | trucuri pentru verificarea sintaxei în Vim
`elpa-flycheck` | V:0.1, I:1.7 | 1130 | verificare sintactică din mers pentru Emacs
`elpa-relint` | I:0.06 | 150 | instrument de detectare a erorilor în expresiile regulate Emacs Lisp
`cppcheck-gui` | V:0.1, I:1.0 | 7697 | instrument pentru analiza statică a codului C/C++ (interfață grafică)
`shellcheck` | V:3, I:16 | 22860 | instrument de analizare sintatică a scripturilor shell
`pyflakes3` | V:1, I:12 | 20 | verificator pasiv al programelor Python 3
`pylint` | V:3, I:17 | 2093 | verificator static al codului Python
`perl` | V:673, I:992 | 836 | interpret cu verificator intern de cod static: `B::Lint`(3perl)
`rubocop` | V:0.1, I:1.1 | 4192 | analizator de cod static Ruby
`clang-tidy` | V:2, I:10 | 21 | instrument de analizare sintactică a codului C++ bazat pe clang
`splint` | V:0.06, I:0.92 | 2325 | instrument pentru verificarea statică a programelor C în vederea depistării erorilor
`flawfinder` | V:0.07, I:0.49 | 187 | instrument pentru examinarea codului sursă C/C++ și identificarea vulnerabilităților de securitate
`black` | V:2, I:13 | 10057 | instrument de formatare a codului Python fără compromisuri
`perltidy` | V:0.4, I:3.1 | 3086 | instrument de indentare și reformatare a scripturilor Perl
`indent` | V:0.8, I:5.1 | 438 | program de formatare a codului sursă în limbajul C
`astyle` | V:0.2, I:2.7 | 770 | instrument de indentare a codului sursă pentru limbajele C, C++, Objective-C, C# și Java
`bcpp` | V:0.02, I:0.26 | 114 | instrument de formatare elegantă pentru C(++)
`xmlindent` | V:0.05, I:0.79 | 52 | instrument de reformatare a fluxului XML
`global` | V:0.2, I:1.6 | 1923 | instrumente de căutare și navigare în codul sursă
`exuberant-ctags` | V:2, I:13 | 341 | creează indexuri ale fișierelor de etichete pentru definițiile codului sursă
`universal-ctags` | V:2, I:10 | 4238 | creează indexuri ale fișierelor de etichete pentru definițiile codului sursă

## 12.5. Depanare

Depanarea este o parte importantă a activităților de programare. Dacă știi să depanezi programele, devii un utilizator Debian competent, capabil să întocmească rapoarte de erori relevante.

Tabel 12.13. Lista pachetelor de depanare

pachet | popcon(popularitate) | dimensiune | documentație
--- | --- | --- | ---
`gdb` | V:88, I:161 | 12453 | «`info gdb`» furnizat de `gdb-doc`
`ddd` | V:0.7, I:5.2 | 4210 | «`info ddd`» furnizat de `ddd-doc`

### 12.5.1. Executarea de bază a gdb

Principalul depanator din Debian este gdb(1), care vă permite să examinați un program în timpul execuției.

Să instalăm `gdb` și programele asociate urmând pașii de mai jos.

    # apt-get install gdb gdb-doc build-essential devscripts

Un bun tutorial despre `gdb` este disponibil:

- «`info gdb`»

- „Depanarea cu GDB” în `/usr/share/doc/gdb-doc/html/gdb/index.html`

- “tutorial în Internet”

Iată un exemplu simplu de utilizare a gdb(1) pe un „`program`” compilat cu opțiunea „`-g`” pentru a genera informații de depanare.

    $ gdb program
    (gdb) b 1                # set break point at line 1
    (gdb) run args           # run program with args
    (gdb) next               # next line
    ...
    (gdb) step               # step forward
    ...
    (gdb) p parm             # print parm
    ...
    (gdb) p parm=12          # set value to 12
    ...
    (gdb) quit

| Indicație
Multe comenzi gdb(1) pot fi abreviate. Extinderea cu tasta «Tab» funcționează la fel ca în shell.

### 12.5.2. Depanarea pachetului Debian

Deoarece toate fișierele binare instalate trebuie să fie curățate de simboluri în sistemul Debian în mod implicit, majoritatea simbolurilor de depanare sunt eliminate din pachetul standard. Pentru a depana pachetele Debian cu gdb(1), trebuie instalate pachetele `*-dbgsym` (de exemplu, `coreutils-dbgsym` în cazul `coreutils`). Pachetele sursă generează automat pachete `*-dbgsym` împreună cu pachetele binare normale, iar aceste pachete de depanare sunt plasate separat în arhiva debian-debug. Vă rugăm să consultați articolele de pe Debian Wiki pentru mai multe informații.

Dacă un pachet care urmează să fie depanat nu include pachetul `*-dbgsym`, trebuie să îl instalați după ce îl recompilați, urmând pașii de mai jos.

    $ mkdir /path/new ; cd /path/new
    $ sudo apt-get update
    $ sudo apt-get dist-upgrade
    $ sudo apt-get install fakeroot devscripts build-essential
    $ apt-get source package_name
    $ cd package_name*
    $ sudo apt-get build-dep ./

Remediați erorile, dacă este necesar.

Actualizați versiunea pachetului la una care nu intră în conflict cu versiunile oficiale Debian, de exemplu una la care se adaugă „`+debug1`” atunci când recompilați o versiune existentă a pachetului, sau una la care se adaugă „`~pre1`” atunci când compilați o versiune a pachetului care nu a fost încă lansată, urmând pașii de mai jos.

    $ dch -i

Compilați și instalați pachetele cu simboluri de depanare urmând pașii de mai jos.

    $ export DEB_BUILD_OPTIONS="nostrip noopt"
    $ debuild
    $ cd ..
    $ sudo debi package_name*.changes

Trebuie să verificați scripturile de compilare ale pachetului și să vă asigurați că utilizați „`CFLAGS=-g -Wall`” pentru compilarea fișierelor binare.

### 12.5.3. Obținerea urmăririi traseului execuției

Când programul se „prăbușește” (crash), este recomandat să trimiteți un raport de eroare care să conțină informațiile traseului de execuție copiate și lipite.

Urmărirea traseului de execuție poate fi obținută prin gdb(1) folosind una dintre următoarele metode:

- Abordarea „Crash-in-GDB”:

  - Rulați programul din GDB.

  - Blocați programul (faceți-l să se prăbușească).

  - Tastați „`bt`” în promptul GDB.

- Abordarea „crash-first”:

  - Actualizați fișierul „/etc/security/limits.conf” pentru a include următoarele:

        * soft core unlimited

  - Tastați «`ulimit -c unlimited`» în promptul shell-ului.

  - Rulați programul din acest prompt shell.

  - Provocați prăbușirea programului pentru a genera un fișier core dump.

  - Încărcați fișierul core dump în GDB folosind comanda «`gdb gdb ./program_binary core`».

  - Tastați „`bt`” în promptul GDB.

În cazul unei bucle infinite sau al blocării tastaturii, puteți forța închiderea programului apăsând `Ctrl-\` sau `Ctrl-C` sau executând comanda „`kill -ABRT PID`”. (Consultați Secțiune 9.4.12, „Omorârea unui proces”)

| Indicație

Adesea, se întâmplă să vezi o urmă de execuție în care una sau mai multe dintre primele linii sunt de tipul „`malloc()`” sau „`g_malloc()`”. Când se întâmplă acest lucru, este foarte probabil ca traseul de execuție să nu fie foarte util. Cea mai simplă modalitate de a găsi informații utile este să configurați variabila de mediu „`$MALLOC_CHECK_`” la valoarea 2 (malloc(3)). Puteți face acest lucru în timp ce rulați `gdb`, urmând pașii de mai jos.

     $ MALLOC_CHECK_=2 gdb hello

### 12.5.4. Comenzi avansate gdb

Tabel 12.14. Lista comenzilor avansate gdb

comandă | descrierea obiectivelor comenzii
--- | ---
`(gdb) thread apply all bt` | obține o urmărire a traseului de execuție pentru toate firele de execuție ale unui program cu mai multe fire de execuție
`(gdb) bt full` | obține parametrii aflați în stiva de apeluri de funcții
`(gdb) thread apply all bt full` | obține o urmărire a traseului de execuției și parametrii ca urmare a combinării opțiunilor anterioare
`(gdb) thread apply all bt full 10` | obțineți o urmărire a traseului de execuție și parametrii pentru primele 10 apeluri, pentru a elimina rezultatele irelevante
`(gdb) set logging on` | înregistrează jurnalul ieșirii `gdb` într-un fișier (implicit este „`gdb.txt`”)

### 12.5.5. Verificați dependențele de biblioteci

Folosiți ldd(1) pentru a afla de ce biblioteci depinde un program, urmând pașii de mai jos.

    $ ldd /usr/bin/ls
            librt.so.1 => /lib/librt.so.1 (0x4001e000)
            libc.so.6 => /lib/libc.so.6 (0x40030000)
            libpthread.so.0 => /lib/libpthread.so.0 (0x40153000)
            /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

Pentru ca ls(1) să funcționeze într-un mediu „chroot”, bibliotecile menționate mai sus trebuie să fie disponibile în mediul „chroot”.

Consultați Secțiune 9.4.6, „Urmărirea activităților programului”.

### 12.5.6. Instrumente de urmărire dinamică a apelurilor

În Debian sunt disponibile mai multe instrumente de urmărire dinamică a apelurilor. Consultați Secțiune 9.4, „Monitorizarea, controlul și inițierea activităților programului”.

### 12.5.7. Depanarea erorilor X

Dacă un program GNOME `preview1` a primit o eroare X, ar trebui să apară următorul mesaj.

    The program 'preview1' received an X Window System error.

În acest caz, puteți încerca să rulați programul cu opțiunea „`--sync`” și să opriți execuția la funcția „`gdk_x_error`” pentru a obține o urmărire a traseului execuției.

### 12.5.8. Instrumente de detectare a „scurgerilor” de memorie

În Debian sunt disponibile mai multe instrumente de detectare a „scurgerilor” de memorie.

Tabel 12.15. Lista instrumentelor de detectare a „scurgerilor” de memorie

pachet | popcon(popularitate) | dimensiune | descriere
--- | --- | --- | ---
`libc6-dev` | V:269, I:584 | 12861 | mtrace(1): funcționalitate de depanare a malloc în glibc
`valgrind` | V:4, I:31 | 89318 | instrument de depanare și optimizare a memoriei
`electric-fence` | V:0.2, I:2.3 | 69 | instrument de depanare malloc(3)
`libdmalloc5` | V:0.01, I:0.61 | 373 | bibliotecă de depanare a alocării memoriei
`duma` | V:0.00, I:0.06 | 297 | bibliotecă pentru detectarea depășirilor și a subutilizărilor de memorie tampon în programele C și C++
`leaktracer` | V:0.01, I:0.33 | 56 | instrument de depistare a scurgerilor de memorie pentru programe C++

### 12.5.9. Dezasamblarea unui fișier binar

Puteți dezasambla codul binar cu objdump(1) urmând pașii de mai jos.

    $  objdump -m i386 -b binary -D /usr/lib/grub/x86_64-pc/stage1

| Notă
gdb(1) poate fi utilizat pentru a dezasambla codul în mod interactiv.

## 12.6. Instrumentele de construcție

Tabel 12.16. Lista pachetelor de instrumente de construire

pachet | popcon(popularitate) | dimensiune | documentație
--- | --- | --- | ---
`make` | V:150, I:566 | 1762 | «`info make`» furnizat de `make-doc`
`autoconf` | V:29, I:200 | 2244 | «`info autoconf`» furnizat de `autoconf-doc`
`automake` | V:28, I:199 | 1932 | «`info automake`» furnizat de `automake1.10-doc`
`libtool` | V:24, I:183 | 1245 | «`info libtool`» furnizat de `libtool-doc`
`cmake` | V:21, I:123 | 59735 | cmake(1) sistem de compilare multiplatformă, cu codul-sursă deschis
`ninja-build` | V:9, I:55 | 456 | ninja(1) un sistem de compilare compact, care se apropie cel mai mult de spiritul Make
`meson` | V:6, I:29 | 4278 | meson(1) sistem de compilare de înaltă productivitate bazat pe `ninja`
`xutils-dev` | V:0.9, I:7.0 | 1495 | imake(1), xmkmf(1), etc.

### 12.6.1. Make

Make este un instrument destinat gestionării grupurilor de programe. La executarea comenzii make(1), `make` citește fișierul de reguli, „`Makefile`”, și actualizează o țintă dacă aceasta depinde de fișiere prealabile care au fost modificate de la ultima modificare a țintei respective sau dacă ținta nu există. Executarea acestor actualizări poate avea loc simultan.

Sintaxa fișierului de reguli este următoarea.

    target: [ prerequisites ... ]
     [TAB]  command1
     [TAB]  -command2 # ignore errors
     [TAB]  @command3 # suppress echoing

Aici „`[TAB]`” reprezintă un cod TAB (codul de tabulare). Fiecare linie este interpretată de shell după ce se efectuează substituirea variabilelor. Folosiți „`\`” la sfârșitul unei linii pentru a continua scriptul. Folosiți „`$$`” pentru a introduce „`$`” ca valori de mediu pentru un script de shell.

Regulile implicite pentru țintă și condițiile prealabile pot fi formulate, de exemplu, după cum urmează.

    %.o: %.c header.h

În acest caz, ținta conține caracterul „`%`” (exact unul). „`%`” poate corespunde oricărui subșir non-vid din numele de fișiere țintă efective. De asemenea, condițiile preliminare utilizează „`%`” pentru a ilustra modul în care numele lor se raportează la numele țintei efective.

Tabel 12.17. Lista variabilelor automate «make»

variabila automată | valoare
--- | ---
`$@` | ținta
`$<` | prima cerință prealabilă
`$?` | toate cerințele prealabile mai recente
`$^` | toate cerințele prealabile
`$*` | „`%`” corespunde cu rădăcina din modelul țintă

Tabel 12.18. Lista expansiunilor variabilelor «make»

expansiunea variabilei | descriere
--- | ---
`foo1 := bar` | expansiune unică
`foo2 = bar` | expansiune recursivă
`foo3 += bar` | adăugare

Rulați «`make -p -f/dev/null`» pentru a vedea regulile interne automate.

### 12.6.2. Autotools

Autotools este o suită de instrumente de programare concepută pentru a facilita portabilitatea pachetelor de cod sursă pe numeroase sisteme de tip Unix.

- Autoconf este un instrument care generează un script shell „`configure`” din „`configure.ac`”.

  - «`configure`» este utilizat ulterior pentru a genera fișierul «`Makefile`» pornind de la șablonul „`Makefile.in`”.

- Automake este un instrument care generează fișierul „`Makefile.in`” din fișierul „`Makefile.am`”.

- Libtool este un script shell care rezolvă problema portabilității software-ului la compilarea bibliotecilor partajate din codul sursă.

#### 12.6.2.1. Compilarea și instalarea unui program

| Avertisment
Nu suprascrieți fișierele de sistem cu programele compilate atunci când le instalați.

Debian nu modifică fișierele din „`/usr/local/`” sau „`/opt`”. Așadar, dacă compilați un program din sursă, instalați-l în „`/usr/local/`”, pentru a nu interfera cu Debian.

    $ cd src
    $ ./configure --prefix=/usr/local
    $ make # this compiles program
    $ sudo make install # this installs the files in the system

#### 12.6.2.2. Dezinstalarea unui program

Dacă dispuneți de sursa originală și dacă aceasta utilizează autoconf(1)/automake(1) și dacă vă amintiți cum ați configurat-o, executați următoarele comenzi pentru a dezinstala programul.

    $ ./configure all-of-the-options-you-gave-it
    $ sudo make uninstall

Alternativ, dacă sunteți absolut sigur că procesul de instalare plasează fișierele numai în directorul „`/usr/local/`” și că acolo nu se află nimic important, puteți șterge tot conținutul acestuia urmând pașii de mai jos.

    # find /usr/local -type f -print0 | xargs -0 rm -f

Dacă nu știți exact unde sunt instalate fișierele, vă recomandăm să folosiți checkinstall(8) din pachetul `checkinstall`, care asigură o dezinstalare completă. Acum acceptă crearea unui pachet Debian cu opțiunea „`-D`”.

### 12.6.3. Meson

Sistemul de construire a software-ului a evoluat:

- Autotools, care a precedat Make, a reprezentat standardul de facto pentru infrastructura de compilare portabilă încă din anii 1990. Acesta este extrem de lent.

- CMake, lansat inițial în 2000, a îmbunătățit semnificativ viteza, dar a fost construit inițial pe baza instrumentului Make, care este lent prin natura sa. În prezent, Ninja poate fi folosit ca motor al acestuia.

- Ninja, lansat inițial în 2012, are rolul de a înlocui Make pentru a îmbunătăți și mai mult viteza de compilare și este conceput astfel încât fișierele sale de intrare să fie generate de un sistem de compilare de nivel superior.

- Meson, lansat inițial în 2013, este un sistem de compilare de nivel superior, popular și rapid, care utilizează Ninja ca motor.

Consultați documentele disponibile la „Sistemul de compilare Meson” și „Sistemul de compilare Ninja”.

## 12.7. Web

Paginile web dinamice și interactive simple pot fi create după cum urmează.

- Întrebările sunt prezentate utilizatorului navigatorului folosind formulare HTML.

- Completarea câmpurilor formularului și apăsarea butonului de trimitere trimite unul dintre următoarele șiruri URL cu parametri codificați din navigator către serverul web.

  - "`https://www.foo.dom/cgi-bin/program.pl?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3`"

  - "`https://www.foo.dom/cgi-bin/program.py?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3`"

  - "`https://www.foo.dom/program.php?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3`"

- „`%nn`” din adresa URL este înlocuit cu un caracter cu valoarea hexazecimală `nn`.

- Variabila de mediu este configurată astfel: "`QUERY_STRING="VAR1=VAL1 VAR2=VAL2 VAR3=VAL3"`".

- Programul CGI (oricare dintre programele de tip „`program.*`”) de pe serverul web se execută cu variabila de mediu „`$QUERY_STRING`”.

- `stdout` ieșirea standard a programului CGI este transmisă către navigatorul web și este afișată sub forma unei pagini web dinamice interactive.

Din motive de securitate, este recomandat să nu creați manual noi metode de analizare a parametrilor CGI. Există module consacrate pentru acest scop în Perl și Python. PHP include deja aceste funcționalități. Când este necesară stocarea datelor pe partea clientului, se utilizează cookie-urile HTTP. Când este necesară procesarea datelor pe partea clientului, se utilizează frecvent Javascript.

Pentru mai multe informații, consultați Common Gateway Interface, The Apache Software Foundation și JavaScript.

Căutarea expresiei „CGI tutorial” în Google, introducând adresa URL codificată https://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial direct în bara de adrese a browserului, este o modalitate bună de a vedea scriptul CGI în acțiune pe serverul Google.

## 12.8. Conversia codului sursă

Există programe pentru conversia codurilor sursă.

Tabel 12.19. Lista instrumentelor de conversie a codului sursă

pachet | popcon(popularitate) | dimensiune | cuvânt-cheie | descriere
--- | --- | --- | --- | ---
`perl` | V:673, I:992 | 836 | AWK→PERL | convertește codurile sursă din AWK în PERL: a2p(1)
`f2c` | V:0.1, I:2.0 | 443 | FORTRAN→C | convertește codurile sursă din FORTRAN 77 în C/C++: f2c(1)
`intel2gas` | V:0.02, I:0.19 | 178 | intel→gas | convertor de la NASM (format Intel) la GNU Assembler (GAS)

## 12.9. Crearea pachetului Debian

Dacă doriți să creați un pachet Debian, citiți informațiile de mai jos.

- Cap. 2, Gestionarea pachetelor Debian pentru a înțelege principiile de bază ale sistemului de pachete

- Secțiune 2.7.13, „Adaptarea unui pachet la sistemul stabil” pentru a înțelege principiile de bază ale procesului de portabilitate

- Secțiune 9.11.4, „Sistemul chroot” pentru a înțelege tehnicile de bază ale „chroot”

- debuild(1), și sbuild(1)

- Secțiune 12.5.2, „Depanarea pachetului Debian” pentru recompilarea în scopul depanării

- Guide for Debian Maintainers - Ghid pentru administratorii Debian (pachetul `debmake-doc`)

- Debian Developer's Reference - Ghidul de referință pentru dezvoltatorii Debian (pachetul `developers-reference`)

- Debian Policy Manual - Manualul de politici Debian (pachetul `debian-policy`)

Există pachete precum `debmake`, `dh-make`, `dh-make-perl` etc., care facilitează procesul de creare a pachetelor.

[7] Este posibil să fie necesare câteva ajustări pentru ca acestea să funcționeze în sistemul actual.

Cap. 11. Conversia datelor |  | Anexa A. Anexa