Autor: Roman Werpachowski <roman@student.ifpan.edu.pl>

Poniej opisuj pokrtce funkcje, ktrych celem jest uatwienie pisania
nowych programw i atanie istniejcych zgodne z mechanizmem HOME-ETC.
Procedury realizuj algorytm opisany przez Pawa Wilka w pliku HOME-ETC.txt w
CVS.

Umownie, katalog w ktrym s zawarte zasoby programw ustawialne przez
uytkownika (zakadki przegldarek, pliki z sygnaturk etc) nazywam ~/data, za
katalog w ktrym s zawarte pliki konfiguracyjne programw nazywam ~/etc.

1. Wskazwki dla uytkownika

W pliku nagwkowym conf_dir.h zdefiniowane s dwie struktury: confdirinfo i fileinfo.

1a. Struktura confdirinfo

typedef struct {
        struct {
                char * config_dir;
                char * data_dir;
                char * home;
        } env;
        char config_dir[MAXPATHLEN + 1];
        char data_dir[MAXPATHLEN + 1];
        char home_dir[MAXPATHLEN + 1];
        int data_dir_exists;
        int config_dir_exists;
	int info_src;
} confdirinfo;

Struktura env przechowuje wskaniki do zmiennych rodowiskowych $CONFIG_DIR,
$DATA_DIR i $HOME. W tablicach config_dir, data_dir i home_dir przechowywane s
utworzone na podstawie zmiennych absolutne nazwy katalogw. Zmienne
data_dir_exists i config_dir_exists s rwne 1, jeli odpowiedni katalog (o
nazwe w  config_dir i data_dir) istnieje. Zmienna info_src jest rwna
CD_FILEINFO, jeli program ma informacj o pooeniu katalogw ~/data i ~/etc
czyta z pliku ~/.etcrc albo (w braku tamtego) z /etc/etcrc, albo CD_ENVINFO,
jeli program w/w informacj uzyska ze zmiennych rodowiskowych CONFIG_DIR i
DATA_DIR.

1b. Struktura fileinfo

typedef struct {
        confdirinfo * common_info;
        char oldpath[MAXPATHLEN];
        char newpath[MAXPATHLEN];
        int movable;
        int oldpath_exists;
        int newpath_exists;
        int oldpath_moved;
} fileinfo;

Struktura fileinfo przechowuje tymczasowe informacje o poszukiwanym pliku oraz
informacje zwracane przez funkcje cd_findconfigfile i cd_finddatafile.
Wskanik common_info wskazuje na struktur opisan w punkcie 1a, zawierajc
informacj wspln dla wszystkich plikw konfiguracyjnych. Tablica oldpath
zawiera po wyjciu z ktrej z w/w dwch procedur "staromodn" ciek dostpu
do szukanego pliku, a tablica newpath zawiera ciek dostpu do pliku
szukanego skonstruowan wg zasad mechanizmu HOME-ETC. Obie cieki dostpu s
konstruowane na podstawie argumentw z jakimi wywoano procedur
cd_findconfigfile albo cd_finddatafile. Zmienna movable okrela, czy wolno
(movable != 1) przenie (jeli istnieje) plik konfiguracyjny z pooenia
wskazywanego przez tablic oldpath do pooenia podanego przez tablic newpath
(jeli istnieje katalog common_info->config_dir). Zmienna oldpath_exists
okrela czy po wyjciu z funkcji cd_findconfigfile (lub cd_finddatafile)
istnia (oldpath_exists != 0) plik o ciece dostpu zawartej w tablicy
oldpath. Analogiczne jest znaczenie zmiennej newpath. Zmienna oldpath_moved
okrela, czy zostao dokonane (oldpath_moved != 0) przeniesienie pliku o
ciece dostpu zawartej w tablicy oldpath w pooenie zawarte w tablicy
newpath.

1c. Sposb uycia procedur

int main(void)
{
        confdirinfo cdi;
        fileinfo fi;
	cdi->info_src = CD_ENVINFO;
        cd_setcommoninfo(&cdi);
        fi.common_info = &cdi;
	/* wolno przenie ~/.testrc do ~/etc/test/testrc */
	fi.movable = 1;
        fname = cd_findconfigfile(NULL, ".testrc", "test", "testrc", &fi);
        printf("%s\n", fname);
	/* wolno przenie ~/lynx_bookmarks.html do ~/data/bookmarks/lynx.html */
        fname = cd_finddatafile(NULL, "lynx_bookmarks.html", "bookmarks", "lynx.html", &fi);
        printf("%s\n", fname);
	fi.movable = 0;
	/* nie wolno przenie ~/.mailcap do /etc/mailcap */
	fname = cd_findconfigfile(NULL, ".mailcap", NULL, "mailcap", &fi);
}

2. Opis waniejszych procedur

2a. void cd_setcommoninfo(confdirinfo * cdi)

Funkcja, w sposb zaleny od wartoci zmiennej cdi->info_src, ustawia zmienne
cdi->env.{config_dir,data_dir,home} (patrz opis procedur cd_getfileinfo i
cd_getenvinfo), nastpnie ustawia zmienne cdi->config_dir, cdi->data_dir i
ewentualnie cdi->home_dir (jeli cdi->info_src == CD_ENVINFO) (patrz opis
funkcji cd_setdirnames). Nastpnie sprawdzone jest istnienie katalogw
cdi->data_dir i cdi->config_dir i ustawiane s zmienne cdi->config_dir_exists i
cdi->data_dir_exists.

2b. int cd_getfileinfo(confdirinfo * cdi)

Przed wywoaniem tej funkcji naley wpisa do tablicy cdi->home_dir ciek
dostpu do katalogu domowego uytkownika.

Zawarto zmiennej cdi->home_dir jest kopiowana do cdi->env.home. Nastpnie
tworzona jest cieka dostpu do pliku ~/.etcrc. Jeli takowego pliku nie da
si otworzy, otwierany jest zamiast niego plik /etc/etcrc, jeli si da --
to otwierany jest ~/.etcrc. W otwartym pliku wyszukiwane s cigi
przyporzdkowa w stylu powoki sh, np. CONFIG_DIR="etc", CONFIG_DIR=etc,
CONFIG_DIR='etc' etc...

Wyszukana warto zmiennej (czyli w kadym z powyszych przykadw cig znakw
"etc" ) jest kopiowana do cdi->env.config_dir). Podobnie, warto nadana
zmiennej DATA_DIR jest kopiowana do cdi->env.data_dir). Poniewa
cdi->env.{home,config_dir,data_dir} s po wykonaniu funkcji cd_getfileinfo
wskanikami do alokowanych tablic, to po odbbnieniu caego ceremoniau ze
znajdowaniem plikw konfiguracyjnych naley wykona procedur cd_freestrings,
zwalniajc przydzielon pami.

Funkcja zwraca -1, jeli nie moga otworzy ~/.etcrc ani /etc/etcrc. Jeli moga, to zwraca 0.

2c. void cd_getenvinfo(confdirinfo * cdi)

Funkcja ustawia cdi->env.{config_dir,data_dir,home} na wskaniki do
odpowiednich zmiennych systemowych (CONFIG_DIR, DATA_DIR, HOME).

2d. void cd_setdirnames(confdirinfo * cdi)

Funkcja kopiuje do cdi->home_dir zawarto cdi->env.home. Nastpnie, jeli
zawarto cdi->env.config_dir zaczyna si od znaku '/', to kopiuje bez zmian
cdi->env.config_dir co cdi->config_dir, w przeciwnym wypadku zawarto
cdi->env.home jest kopiowana do cdi->config_dir i doklejana do niej jest
zawarto cdi->env.config_dir. Podobnie traktowana jest zmienna
cdi->env.data_dir. Z obu zmiennych cdi->config_dir i cdi->data_dir usuwane s
powtarzajce si ukoniki i koczcy ukonik.

2e. char * cd_findconfigfile(const char * oldsubdir, const char * oldname, const char * newsubdir, const char * newname, fileinfo * fi)

Funkcja bierze jako argumenty: const char * oldsubdir - podkatalog katalogu domowego w ktrym mog si znajdowa stare (tj. nie-HOME-ETC) pliki konfiguracyjne (moe by NULL, jeli lea one w ~), const char * oldname - nazwa starego pliku konfiguracyjnego, const char * newsubdir - podkatalog katalogu CONFIG_DIR w ktrym powinien si znajdowa plik konfiguracyjny const char *  newname, const char * newname - nazwa pliku konfiguracyjnego w pooeniu zgodnym z mechanizmem HOME-ETC, fileinfo * fi - struktura zawierajca wskanik do struktury commoninfo z danymi oglnymi i zmienne w ktrych znajdowa si bd wyniki dziaania funkcji cd_findconfigfile. Funkcja realizuje algorytm opisany przez Pawa Wilka, na wyjciu w fi->oldpath znajduje si skonstruowana z oldsubdir i oldname stara nazwa pliku, w fi->newpath znajduje si skonstruowana z newsubdir i newname nowa nazwa pliku. fi->oldpath_exists == 1 jeli w momencie wyjcia z funkcji istnia plik fi->oldpath, fi->newpath_exists == 1 jeli w momencie wyjcia z funkcji istnia plik fi->newpath. fi->oldpath_moved == 1 jeli fi->oldpath zosta w trakcie wykonania funkcji przeniesiony do fi->newpath. W przeciwnych przypadkach te trzy zmienne s rwne 0.

Funkcja zwraca wskanik do fi->oldpath albo fi->newpath, zalenie od tego ktra jest dobra. S to wskaniki do tablic statycznych!

2f. char * cd_finddatafile(const char * oldsubdir, const char * oldname, const char * newsubdir, const char * newname, fileinfo * fi)

Dziaanie takie samo jak cd_findconfigfile. Jedyn rnic jest, e ,,nowy''
katalog to ten wskazywany przez zmienn DATA_DIR.
