<!-- $Id$ -->
<sect1 id="tscript" xreflabel="T-Script">
<title>T-Script</title>
	<sect2 id="tscript-intro">
	<title>Wstęp</title>
		<para>Głównym przeznaczeniem języka skryptowego <ulink url="http://silvercoders.com/index.php?page=T_Script">T-Script</ulink>,
		jest generowanie plików tekstowych. Może być
		używany do przetwarzania szablonów z danymi pobieranymi z różnych
		źródeł np. baz SQL lub plików tekstowych.</para>
		<para>Przed kompilacją T-Scripta upewnij się, że posiadasz w systemie
		pakiety <filename>bison</filename> (co najmniej w wersji 1.875) oraz 
		<filename>flex</filename>.</para>
	</sect2>
	<sect2 id="tscript-syntax">
	<title>Składnia</title>
		<para>Składnia języka T-Script jest podobna do składni innych popularnych
		języków takich jak C czy JavaScript, ale dokonano pewnych zmian
		mających na celu ułatwienie tworzenia szablonów. 
		Wszystkie podane polecenia powinny być zapisywane wewnątrz klamer { }.
		Dane poza klamrami zostaną zapisane do pliku wyjściowego (lub jeśli go
		nie zdefiniowano, pominięte). Wielkość liter ma znaczenie. Do oddzielenia
		poleceń służy znak średnika.</para>
		<sect3 id="expr">
		<title>Wyrażenia i operatory</title>
			<itemizedlist>
			<listitem>
				<para>Ciąg znaków. Obowiązują tutaj zasady języka C dotyczące użycia znaków formatujących (\t, \n, \\). </para>
				<para>Przykład: <prompt>"jakiś ciąg znaków"</prompt></para>
			</listitem>
			<listitem>
				<para>Liczba.</para>
				<para>Przykład: <prompt>1234</prompt></para>
			</listitem>
			<listitem>
				<para>Wartość zmiannej "var".</para>
				<para>Przykład: <prompt>var</prompt></para>
			</listitem>
			<listitem>
				<para>N-ty element tablicy "var".</para>
				<para>Przykład: <prompt>var[n]</prompt></para>
			</listitem>
			<listitem>
				<para>Podzmienna "n" zmiennej "var".</para>
				<para>Przykład: <prompt>var.n</prompt></para>
			</listitem>
			<listitem>
				<para>Wartość wyrażenia w nawiasach.</para>
				<para>Przykład: <prompt>( wyrażenie )</prompt></para>
			</listitem>
			<listitem>
				<para>Słowo kluczowe "null". Określa wartość niezdefiniowaną.
				Przydatne do sprawdzania, czy jakaś zmienna (wartość) jest
				zdefiniowana.</para>
				<para>Przykład: <prompt>zmienna = null</prompt></para>
			</listitem>
			<listitem>
				<para>Porównania. Zwraca wynik logiczny porównania.</para>
				<para>Przykład: 
<screen>
wyrażenie1 == wyrażenie2;
wyrażenie1 != wyrażenie2;
wyrażenie1 &lt; wyrażenie2;
wyrażenie1 &gt; wyrażenie2;
wyrażenie1 &lt;= wyrażenie2;
wyrażenie1 &gt;= wyrażenie2;
</screen></para>
			</listitem>
			<listitem>
				<para>Operatory binarne. Suma i iloczyn bitowy.</para>
				<para>Przykład: <prompt>wyrażenie1 | wyrażenie2</prompt></para>
				<para>Przykład: <prompt>wyrażenie1 & wyrażenie2</prompt></para>
			</listitem>
			<listitem>
				<para>Operatory logiczne.</para>
				<para>Przykład: <prompt>wyrażenie1 || wyrażenie2</prompt></para>
				<para>Przykład: <prompt>wyrażenie1 && wyrażenie2</prompt></para>
				<para>Przykład: <prompt>! wyrażenie1</prompt></para>
			</listitem>
			<listitem>
				<para>Łączenie ciągów znaków. Gdy oba wyrażenia nie są liczbami 
				traktuje je jako ciągi znaków i dokonuje ich połączenia.</para>
				<para>Przykład: <prompt>wyrażenie1 + wyrażenie2</prompt></para>
			</listitem>
			<listitem>
				<para>Operatory arytmetyczne. Zwraca wynik operacji arytmetycznej na dwóch wyrażeniach.</para>
				<para>Przykład: 
<screen>
wyrażenie1 + wyrażenie2;
wyrażenie1 - wyrażenie2;
wyrażenie1 * wyrażenie2;
wyrażenie1 / wyrażenie2;
wyrażenie1 % wyrażenie2;
</screen></para>
			</listitem>
			<listitem>
				<para>Jednoargumentowe operatory inkrementacji/dekrementacji.</para>
				<para>Przykład: <prompt>wyrażenie++</prompt></para>
				<para>Przykład: <prompt>wyrażenie--</prompt></para>
				<para>Przykład: <prompt>++wyrażenie</prompt></para>
				<para>Przykład: <prompt>--wyrażenie</prompt></para>
			</listitem>
			<listitem>
				<para>Przesunięcie bitowe.</para>
				<para>Przykład: <prompt>wyrażenie1 &gt;&gt; wyrażenie2</prompt></para>
				<para>Przykład: <prompt>wyrażenie1 &lt;&lt; wyrażenie2</prompt></para>
			</listitem>
			<listitem>
				<para>Porównanie ciągu do z wyrażeniem regularnym. Zwraca 1 gdy <prompt>wyrażenie</prompt>
				pasuje do wzorca po prawej stronie, w przeciwnym wypadku zwraca 0.</para>
				<para>Przykład: <prompt>wyrażenie =~ wzorzec</prompt></para>
			</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="comments">	
		<title>Komentarze</title>
			<itemizedlist>
				<listitem>
					<para>Komentarz w stylu języka C.</para>
					<para>Przykład: <prompt>/* to jest komentarz - może być wieloliniowy */</prompt></para>
				</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="commands">
		<title>Polecenia</title>
			<itemizedlist>
				<listitem>
					<para>Przypisanie. Przypisanie wartości wyrażenia do podanej zmiennej.</para>
					<para>Przykład: <prompt>zmienna = wyrażenie</prompt></para>
				</listitem>
				<listitem>
					<para>Wyrażenie warunkowe. Wykonanie polecenia tylko wtedy gry wyrażenie jest prawdą. 
					Druga forma wykonuje polecenie1 gdy wyrażenie jest prawdą lub polecenie2
					gdy jest fałszem.</para> 
					<para>Przykład: <screen>
if ( wyrażenie ) polecenia /if
if ( wyrażenie ) polecenie1 else polecenie2 /if
</screen></para>
				    	<para>Tekst między blokami jest traktowany jako polecenia
				    	dlatego następujący przykład jest prawidłowy: <screen>
Jakiś tekst
{if (a==1)} 
a równe jest 1
{else} 
a nie jest równe 1
{/if} 
</screen>
					Można wstawić backslash (\) pomiędzy poleceniem a końcem wiersza aby
					pozbyć się znaku końca linii i zachować normalny (bez załamania linii w tym miejscu)
					przepływ tekstu. Na przykład: <screen>
Jakiś tekst
{if (a==1)}\ 
a równa się 1 
{else}\ 
a nie równa się 1 
{/if}\
</screen></para>
				</listitem>
				<listitem>
					<para>Pętla iteracyjna. Wykonuje wyrażenie <prompt>wyrażenie1</prompt> jako
					polecenie inicjalizujące pętlę. Następnie wykonywane jest 
					<prompt>wyrażenie3</prompt> i <prompt>polecenie</prompt> dopóki 
					<prompt>wyrażenie2</prompt> jest prawdziwe.</para>
					<para>Przykład: <screen>for ( wyrażenie1 ; wyrażenie2 ; wyrażenie3 ) polecenie /for</screen></para>
				</listitem>
				<listitem>
					<para>Konstrukcja <prompt>foreach</prompt>. Pozwala na iterację po wszystkich
					elementach danej tablicy. Wykunuje <prompt>polecenia</prompt> tyle razy ile 
					jest w tablicy elementów podstawiając za każdym razem wartość odpowiedniego 
					elementu tablicy pod <prompt>element</prompt>.</para>
					<para>Przykład: <screen>foreach ( element in tablica ) polecenia /foreach</screen></para>
				</listitem>
				<listitem>
					<para>Pętla <prompt>while</prompt>. Wykonanuje <prompt>polecenie</prompt>
					tak długo jak długo <prompt>wyrażenie</prompt>  jest prawdziwe. Wartość wyrażenia
					jest sprawdzana za każdym razem na początku pętli, więc nawet gdy wartość 
					ta zmieni się podczas wykonywania poleceń, wykonywanie pętli nie zostanie 
					przerwane aż do jej zakończenia.</para>
					<para>Przykład: <screen>while ( wyrażenie ) polecenie /while</screen></para>
				</listitem>
				<listitem>
					<para><prompt>break</prompt>. Polecenie to kończy wykonywanie
					aktualnej instrukcji pętli.</para>
					<para>Przykład: 
<screen>
{for (i = 0; i &lt; 10; i++)}\
{if (i == 5)}{break}{/if}\
: {i}
{/for}\
</screen></para>
				</listitem>
				<listitem>
					<para><prompt>continue</prompt>. Polecenie <prompt>continue</prompt>
					używane jest wewnątrz instrukcji pętli do przerwania wykonania
					danej iteracji pętli i rozpoczęcia kolejnej iteracji.</para>
					<para>Przykład: 
<screen>
{for (i = 0; i &lt; 10; i++)}\
{if (i == 5)}{continue}{/if}\
: {i}
{/for}\
</screen></para>
				</listitem>
				<listitem>
					<para><prompt>exit</prompt>. Polecenie to służy po prostu do
					przerwania wykonywania skryptu.</para>
					<para>Przykład: 
<screen>
{if (zmienna &gt; 0)
    exit;
/if}
</screen></para>
				</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="functions">
		<title>Funkcje</title>
			<para>Funkcje mogą być używane zarówno w składni z nawiasem
			(<prompt>{funkcja(zmienna)}</prompt>) jak i bez nawiasu 
			(<prompt>{funkcja {zmienna}}</prompt>).
			<itemizedlist>
				<listitem>
					<para><prompt>string(liczba)</prompt></para>
					<para>Zamiana wartości liczbowej na ciąg znaków.</para>
					<para>Przykład: <prompt>string(zmienna)</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>number(ciąg_znaków)</prompt></para>
					<para>Zamiana ciągu znaków na liczbę. Dla tablic zwraca ilość elementów w tablicy.</para>
					<para>Przykład: <prompt>number("123")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>typeof(zmienna)</prompt></para>
					<para>Sprawdzenie typu. Zwraca nazwę typu zmiennej np.string, 
					number, array, null.</para>
					<para>Przykład: <prompt>typeof(zmienna)</prompt></para>
				</listitem>
			</itemizedlist>
			W skrypcie powyższe funkcje mogą być użyte w następujący sposób:
<screen>
{x = 5}x = {x}
{var = "3"}var = {var}
x + var = {x + var}
x + var = {number(var) + x}
x + var = {string(x) + var}
x jest typu {typeof(x)}
var jest typu {typeof(var)}
</screen></para>
		</sect3>
	</sect2>
	<sect2 id="extensions">
	<title>Rozszerzenia</title>
		<para>Rozszerzenia (extensions) to dodatki do biblioteki <emphasis>tscript</emphasis>. Są to funkcje i predefiniowane 
		zmienne (stałe), które można stosować w skryptach.</para>
		<sect3 id="exec">
		<title>Exec</title>
			<para>Wykonywanie poleceń powłoki umożliwia funkcja 
			<prompt>exec()</prompt>.
			Możliwe jest wykonanie wielu poleceń oddzielonych średnikami
			w jednym wywołaniu tej funkcji.</para>
			<itemizedlist>
				<listitem>
					<para><prompt>exec(polecenie)</prompt></para>
					<para>Wykonywanie poleceń powłoki.</para>
					<para>Przykład: <prompt>exec("rm -f /")</prompt></para>
				</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="string">
		<title>String</title>
			<para><prompt>String</prompt> zawiera podstawowe funkcje do operowania
			na ciągach znaków.</para>
			<itemizedlist>
				<listitem>
					<para><prompt>trim(ciąg_znaków)</prompt></para>
					<para>Usunięcie "białych" znaków z początku i końca 
					ciągu znaków.</para>
					<para>Przykład: <prompt>trim("   aaa   ")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>len(ciąg_znaków)</prompt></para>
					<para>Zwraca długość ciągu (odpowiednik funkcji strlen() z języka C).</para>
					<para>Przykład: <prompt>length = len(string)</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>replace(wzorzec, zamiennik, ciąg_znaków)</prompt></para>
					<para>Funkcja przeszukuje ciąg_znaków w poszukiwaniu fragmentów pasujących
					do wzorca i wstawia w jego miejsce zamiennik. Wzorzec może być
					wyrażeniem regularnym zgodnym z POSIX.</para>
					<para>Przykład: <prompt>replace(":", "-", mac)</prompt></para>
					<para>Przykład: <prompt>replace("[a-z]", "-", "teksty")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>explode(separator, ciąg_znaków)</prompt></para>
					<para>Zwraca tablicę ciągów, powstałych z podziału ciągu_znaków
					wg określonego separatora. Separator może być POSIX'owym wyrażeniem
					regularnym.</para>
					<para>Przykład: <prompt>explode(":", "aaa:bbb:ccc")</prompt></para>
					<para>Przykład: <prompt>explode("[ ]+", "aaa bbb ccc")</prompt></para>
				</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="sysinfo">
			<title>Sysinfo</title>
			<para>Rozszerzenie o nazwie <prompt>Sysinfo</prompt> zawiera 
			funkcje pobierające dane z systemu.</para>
			<itemizedlist>
				<listitem>
					<para><prompt>date([ciąg_formatujący])</prompt></para>
					<para>Bieżąca data i czas wg zadanego formatu.
					Domyślnie funkcja zwraca datę w formacie %Y/%m/%d. 
					Znaczenie poszczególnych specyfikatorów konwersji można
					znaleźć w <prompt>`man strftime`</prompt>.</para>
					<para>Zwracany obiekt zawiera predefiniowane podzmienne
					<prompt>year</prompt>, <prompt>month</prompt>, <prompt>day</prompt>, 
					<prompt>hour</prompt>, <prompt>minute</prompt>, <prompt>second</prompt></para> 
					<para>Przykład: 
<screen>
{date("%s") / zwraca bieżący czas w formacie unix timestamp */}
{a = date()}
{a.month /* zwraca numer bieżącego miesiąca */ }
</screen></para>
				</listitem>
				<listitem>
					<para><prompt>systype</prompt></para>
					<para>Typ systemu. Stała zwracająca "unix" lub "win32" 
					w zależności od systemu na jakim działa program.</para>
					<para>Przykład: 
<screen>
{if (systype == "unix")}\
{exec echo wykonujemy polecenie powłoki}\
{else}\
tu nie mamy powłoki
{/if}\
</screen></para>
				</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="file">
			<title>File</title>
			<para>To rozszerzenie udostępnia podstawowe operacje na plikach.
			<itemizedlist>
				<listitem>
					<para><prompt>file(nazwa_pliku)</prompt></para>
					<para>Przekierowanie wyjścia. Dane zostaną dopisane
					do podanego pliku.</para>
					<para>Przykład: <screen>{file nazwa_pliku} polecenia {/file}</screen></para>
				</listitem>
				<listitem>
					<para><prompt>fileexists(nazwa_pliku)</prompt></para>
					<para>Jeśli plik istnieje zwraca 1, w przeciwnym wypadku 0.</para>
					<para>Przykład: <screen>{if fileexists(plik)}{deletefile(plik)}{/if}</screen></para>
				</listitem>
				<listitem>
					<para><prompt>deletefile(nazwa_pliku)</prompt></para>
					<para>Usunięcie pliku.</para>
					<para>Przykład: <prompt>deletefile("/tmp/plik.txt")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>readfile(nazwa_pliku)</prompt></para>
					<para>Zapisuje w tablicy zawartość pliku tak, że każda
					linia pliku to osobny element tablicy.</para>
					<para>Przykład: <prompt>readfile("/tmp/plik.txt")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>getfile(nazwa_pliku)</prompt></para>
					<para>Zwraca całą zawartość pliku.</para>
					<para>Przykład: <prompt>getfile("/tmp/plik.txt")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>listdir(katalog)</prompt></para>
					<para>Zwraca listę plików (i podkatalogów) w tablicy. Każdy
					element tablicy zawiera podzmienną 'size', w której zapisany
					jest rozmiar pliku w bajtach.</para>
					<para>Przykład: <prompt>listdir("/home/alec")</prompt></para>
				</listitem>
			</itemizedlist>
			Poniższy listing prezentuje przykładowy skrypt z użyciem wszystkich funkcji
			rozszerzenia <prompt>File</prompt>.
<screen>
{list = listdir("/home/alec/lms/doc")}
{for (x = 0; x &lt; number(list); x++) }\
{list[x]}--{list[x].size}
{/for}\
{file "/home/alec/plik.txt"}
Linia 1
Linia 2
{/file}\
{f = readfile /home/alec/plik.txt}\
{for (i = 0; i &lt; number(f); i++) }\
linia {i}: {f[i]}\
{/for}\
{f = getfile /home/alec/plik.txt}\
{f}
{deletefile /home/alec/plik.txt}\
</screen></para>
		</sect3>
		<sect3 id="syslog">
			<title>Syslog</title>
			<para>Rozszerzenie o nazwie <prompt>Syslog</prompt> zawiera 
			funkcję pozwalającą na zapisywanie komunikatów do logów systemowych.
			Wprowadza róznież definicje poziomów ważności komunikatów.</para>
			<itemizedlist>
				<listitem>
					<para><prompt>syslog(ciąg [, poziom])</prompt></para>
					<para>Funkcja zapisuje do logów systemowych komunikat
					określony przez argument <prompt>ciąg</prompt>. Drugi 
					argument funkcji jest opcjonalny i definiuje poziom
					ważności komunikatu, który domyślnie ustawiony jest 
					na <prompt>LOG_INFO</prompt>
					(patrz <prompt>man 3 syslog</prompt>).</para>
					<para>Przykład: 
<screen>
syslog("Komunikat", LOG_ERR);
syslog("Komunikat");
</screen></para>
				</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="net">
			<title>Net</title>
			<para>W tym rozszerzeniu zawarte są funkcje (nazwy pisane małymi literami)
				przeznaczone do operowania na adresach IP i maskach. Jest to rozszerzenie
				dodane w LMS.</para>
			<itemizedlist>
				<listitem>
					<para><prompt>mask2prefix(ciąg_znaków)</prompt></para>
					<para>Zamiana maski sieciowej w formacie xxx.xxx.xxx.xxx
						na liczbę (bitów).</para>
					<para>Przykład: <prompt>mask2prefix("255.255.255.0")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>ip2long(ciąg_znaków)</prompt></para>
					<para>Zamiana adresu IP w formacie 4-oktetowym na
						liczbę.</para>
					<para>Przykład: <prompt>ip2long("192.168.0.1")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>long2ip(liczba)</prompt></para>
					<para>Zamiana adresu IP podanego jako liczba
						na format xxx.xxx.xxx.xxx.</para>
					<para>Przykład: <prompt>long2ip(zmienna)</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>broadcast(adres, maska)</prompt></para>
					<para>Obliczenie adresu broadcast dla podanego
					adresu IP oraz maski (format maski dowolny).</para>
					<para>Przykład: <prompt>broadcast("192.168.0.1", "255.255.255.0")</prompt></para>
				</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="sql">
		<title>SQL</title>
			<para>Rozszerzenie SQL udostępnia podstawowe funkcje związane
			z obsługą bazy danych. Pozwala na wykonywanie poleceń SQL.</para>
			<itemizedlist>
				<listitem>
					<para>Polecenia SQL: <prompt>SELECT</prompt>, <prompt>INSERT</prompt>,
					<prompt>DELETE</prompt>, <prompt>UPDATE</prompt>, <prompt>CREATE</prompt>, 
					<prompt>DROP</prompt>.</para>
					<para>Przykład: <screen>
{SELECT * FROM tabela}
{INSERT INTO tabela VALUES(1)}
{DELETE FROM tabela}
{UPDATE tabela SET kolumna=1}
{CREATE TABLE foo (bar integer)}
{DROP TABLE foo}</screen></para>
				</listitem>
				<listitem>
					<para><prompt>rows(zapytanie)</prompt></para>
		        		<para>Liczba wierszy, których dotyczy zapytanie.</para>
		        		<para>Przykład: <prompt>rows("SELECT * FROM tabela")</prompt></para>
				</listitem>
				<listitem>
					<para><prompt>escape(ciąg_znaków)</prompt></para>
				        <para>Zabezpieczenie znaków specjalnych w celu użycia
					w zapytaniu SQL. W szczególności chodzi o apostrofy 
					i backslashe. Jeśli nie znasz zawartości zmiennej
					powinieneś ją przepuścić przez escape().</para>
				        <para>Przykład: <prompt>SELECT * FROM tabela WHERE name={escape(zmienna)}</prompt></para>
				</listitem>
			</itemizedlist>
		</sect3>
		<sect3 id="consts">
		<title>Stałe</title>
			<para>Rozszerzenie ściśle związane z LMS-em. Umożliwia
			tworzenie skryptów bez znajomości struktury bazy danych.
			Zawiera predefiniowane stałe, które zawierają dane z bazy.
			Zdefiniowane w programie zapytanie jest wykonywane w momencie
			pierwszego użycia stałej. Nazwy stałych należy pisać
			dużymi literami. Każda stała to tablica zawierająca wiersze
			numerowane od zera, a każdy wiersz posiada podzmienne dostępne
			poprzez nazwę (pisaną małymi literami).</para>
			<itemizedlist>
				<listitem>
					<para>CUSTOMERS - lista klientów:
					<simplelist>
					<member>id - ID klienta</member>
					<member>lastname - nazwa/nazwisko klienta</member>
					<member>name - imię klienta</member>
					<member>status - status</member>
					<member>address - adres klienta</member>
					<member>zip - kod pocztowy</member>
					<member>city - miasto</member>
					<member>email - adres e-mail</member>
					<member>ten - numer NIP</member>
					<member>ssn - numer PESEL</member>
					<member>regon - numer REGON</member>
					<member>icn - numer dowodu osobistego</member>
					<member>rbe - numer EDG/KRS</member>
					<member>info - informacje o kliencie</member>
					<member>message - treść ostrzeżenia</member>
					<member>warning - status ostrzeżenia (suma statusów wszystkich komputerów klienta)</member>
					<member>access - status dostępności (suma statusów wszystkich komputerów klienta)</member>
					<member>balance - bilans klienta</member>
					</simplelist>
					</para>
				</listitem>
				<listitem>
					<para>NODES - lista komputerów (i adresów urządzeń sieciowych):
					<simplelist>
					<member>id - ID komputera</member>
					<member>owner - nazwa/nazwisko i imię 	klienta</member>
					<member>ownerid - ID klienta ('0' w przypadku urządzeń)</member>
					<member>name - nazwa komputera (adresu urządzenia)</member>
					<member>access - status: włączony/wyłączony (1/0)</member>
					<member>warning - status ostrzeżeń: włączone/wyłączone (1/0)</member>
					<member>netdev - ID urządzenia, do którego jest podłączony</member>
					<member>lastonline - czas ostatniej aktywności</member>
					<member>info - dodatkowe 	informacje</member>
					<member>message - treść ostrzeżenia</member>
					<member>mac - adres MAC</member>
					<member>passwd - hasło</member>
					<member>ip - adres IP</member>
					<member>ip_pub - publiczny adres IP</member>
					<member>linktype - typ połączenia (0-kabel, 1-radio)</member>
					<member>port - numer portu urządzenia, do którego podłączony jest komputer</member>
					<member>chkmac - sprawdzanie MAC'a: włączone/wyłączone (1/0)</member>
					<member>halfduplex - rodzaj komunikacji (0-full, 1-half)</member>
					</simplelist>
					</para>
				</listitem>
				<listitem>
		        		<para>NETWORKS - lista sieci:
					<simplelist>
					<member>id - ID sieci</member>
					<member>name - nazwa sieci</member>
					<member>address - adres IP</member>
					<member>mask - maska 	(xxx.xxx.xxx.xxx)</member>
					<member>prefix - liczba jedynek w masce</member>
					<member>size - rozmiar sieci (ilość adresów)</member>
					<member>interface - nazwa interfejsu</member>
					<member>gateway - adres bramy</member>
					<member>dns - adres pierwszego serwera DNS</member>
					<member>dns2 - adres drugiego serwera DNS</member>
					<member>wins - adres WINS</member>
					<member>domain - nazwa domenowa</member>
					<member>dhcpstart - początek zakresu DHCP</member>
					<member>dhcpend - koniec zakresu DHCP</member>
					</simplelist>
					</para>
				</listitem>
			</itemizedlist>
		</sect3>
	</sect2>
	<sect2 id="examples">
	<title>Przykładowe skrypty</title>
		<para>Zacznijmy od bardzo prostego skryptu, który tworzy plik
		<filename>/etc/hosts</filename> z listą adresów i nazw komputerów 
		(oraz urządzeń).
		<example id="tscript-example-hosts">
		<title>Parser: Tworzenie pliku /etc/hosts</title>
<screen>
{result = SELECT name, inet_ntoa(ipaddr) AS ip FROM nodes}\
127.0.0.1    localhost
{for (r=0; r&lt;number(result); r++)}\
{result[r].name}{"\t"}{result[r].ip}
{/for}\
</screen>
		</example></para>
		<para>Utworzenie listy dłużników jest bardzo proste, zwłaszcza
		gdy zastosujemy jedną z predefiniowanych stałych.
		<example id="tscript-example-debtors">
		<title>Parser: Lista dłużników</title>
<screen>
{
for (r=0; r&lt;number(CUSTOMERS); r++)
    if (CUSTOMERS[r].balance < 0)
}\
{CUSTOMERS[r].lastname} {CUSTOMERS[r].name}{"\t"}{CUSTOMERS[r].balance}
{
    /if
/for}\
</screen>
		</example></para>
		<para>Utworzenie listy z opisami komputerów dla programu iptraf. Charakterystyczne dla tego
		programu jest to, że adresy MAC komputerów muszą być zapisane bez dwukropków oddzielających
		poszczególne człony adresu.
		<example id="tscript-example-iptraf">
		<title>Parser: Opisy komputerów dla iptrafa.</title>
<screen>
{list = SELECT LOWER(mac) AS mac, UPPER(name) AS name, inet_ntoa(ipaddr) AS ip from nodes}\
{for(i=0; i&lt;number(list); i++)}\
{replace(":","",list[i].mac)}:{list[i].name} {list[i].ip}
{/for}
</screen>
		</example></para>
		<para>W następnym przykładzie tworzymy plik z przypisanymi adresami IP do adresów sprzętowych
		hostów, używany przez program <filename>arp</filename>. Hostom z wyłączonym dostępem
		zostaną przypisane "puste" MACi.
		<example id="tscript-example-ethers">
			<title>Parser: Plik "ethers" dla programu arp.</title>
			<screen>
{if (number(NODES))
       if (fileexists("/etc/ethers"))
               deletefile("/etc/ethers");
       /if; 
       for (i=0; i&lt;number(NODES); i++)
               if (number(NODES[i].access))
                      }{NODES[i].mac}{"\t"}{NODES[i].ip}{"\n"}{
               else
                      }00:00:00:00:00:00{"\t"}{NODES[i].ip}{"\n"}{
               /if;
      /for;
/if}\
</screen>
		</example>
		</para>
		<para>Kolejny trochę dłuższy przykład, w którym wykorzystujemy głównie
		<prompt>exec</prompt>. Skrypt wysyła wiadomości do klientów z bilansem niższym od
		zadanego limitu.
		<example id="tscript-example-notify">
		<title>Parser: Zamiennik modułu notify</title>
<screen>
{limit = 0;
dt = date();
customers = SELECT customers.id AS id, email, pin, name, lastname,
        SUM((type * -2 +7) * cash.value) AS balance
        FROM customers
        LEFT JOIN cash ON customers.id = cash.customerid AND (cash.type = 3 OR cash.type = 4)
        WHERE deleted = 0 AND email!=''
        GROUP BY customers.id, name, lastname, email, pin
        HAVING SUM((type * -2 +7) * cash.value) &lt; {limit}
}
{for(i=0; i&lt;number(customers); i++)}

    {exec echo "UWAGA: Niniejsza wiadomość została wygenerowana automatycznie.

Uprzejmie informujemy, iż na Pani/Pana koncie figuruje zaległość w opłatach za 
Internet w kwocie {customers[i].balance*-1} zł.

Jeżeli należność za bieżący miesiąc, to jest {dt.month}-{dt.year}, została już
uregulowana prosimy zignorować tę wiadomość.

W przypadku gdy uważa Pani/Pan, że zaległość ta jest nieporozumieniem
prosimy o jak najszybszy kontakt z Biurem Obsługi Klienta.

Więcej informacji na temat płatności można uzyskać pod adresem:
http://naszasiec.pl/mojekonto/

W celu uregulowania należności prosimy o kontakt:

Nasz Siec ASK - Biuro Obsługi Klienta
Gwidon Mniejważny
telefon: 0-606031337
e-mail: gwidonm@naszasiec.pl

PS. Poniżej załączamy ostatnie 10 operacji na Państwa koncie.
--------------+--------------+-----------------------------
     Data     |    Kwota     |           Komentarz
--------------+--------------+-----------------------------" &gt; /tmp/mail}

    {last10 = SELECT comment, time, CASE WHEN type=4 THEN value*-1 ELSE value END AS value
            FROM cash WHERE customerid = {customers[i].id}
            ORDER BY time DESC LIMIT 10}
    
    {for(j=0; j&lt;number(last10); j++)}
    
        {exec echo "{last10[j].time}|{"\t"}{last10[j].value}|{"\t"}{last10[j].comment}" &gt;&gt; /tmp/mail}
    
    {/for}

    {exec mail -s "Powiadomienie o zaleglosciach" -r lms@domain.tld {customers[i].email} &lt; /tmp/mail}

{/for}
</screen>
		</example>
		</para>
		<para>Kolejny rozbudowany przykład to odpowiednik modułu traffic.
		Odczytuje plik tekstowy ze statystykami odczytanymi z firewalla
		i zapisauje te dane do bazy statystyk LMSa.
		<example id="tscript-example-traffic">
			<title>Parser: Statystyki.</title>
			<screen>
{
log = "/var/log/traffic.log";
nodes = SELECT id, INET_NTOA(ipaddr) AS ip, INET_NTOA(ipaddr_pub) AS ip_pub FROM nodes;
if(! fileexists(log))
    exit;
/if;
lines = readfile(log);
n = number(nodes);
for (i=0; i&lt;number(lines); i++)
    line = explode("[[:blank:]]+", lines[i]); /* file format: IP upload download */
    if ( number(line) == 3  && (line[1] &gt; 0 || line[2] &gt; 0) )
        for (x=0; x&lt;n; x++)
            if (nodes[x].ip == line[0] || nodes[x].ip_pub == line[0] )
                id = nodes[x].id;
                break;
            /if;
        /for;
        if (x &lt; n)
            INSERT INTO stats (nodeid, dt, download, upload) VALUES ({id}, %NOW%, {line[2]}, {line[1]});
        /if;
    /if;
/for;
}	
</screen>
		</example>
		</para>
	</sect2>
</sect1>
