OpenBSD: Ricerca ed installazione pacchetti con OPM

Gestire i pacchetti per OpenBSD in modo semplice.

Descrizione:

OPM (OpenBSD Packages Manager) è un gestore di pacchetti per OpenBSD.
Attualmente è in grado di cercare, installare, rimuovere, mostrare informazioni circa qualsiasi package disponibile sugli ftp OpenBSD.

Downloads:

Possiamo trovare la versione beta del software all'indirizzo: http://www.openbeer.it/codes/projects/OPM-0.1beta.tar.gz

La versione testing-unstable da CVS, invece, la troviamo qui: http://sickfreak.shacknet.nu/cgi-bin/cvsweb/OpenBSD_Packages_Manager/

Installazione:

Per installare OPM è sufficiente scaricare il tarbal ed eseguire lo script install.sh o, qualora si volesse fare a mano, compilare opm.c con gcc opm.c -o opm -L/usr/local/lib -I/usr/local/include -lcurl e copiare l'eseguibile opm nel path dei nostri binari (di solito /usr/bin).

Installare un pacchetto:

OpenBSD Packages Manager ci permette di installare un pacchetto e le relative dipendenze molto semplicemente.
Il software si occuperà di recuperare il pacchetto di nostro interesse dai server FTP del progetto OpenBSD, scaricato il pacchetto lo affiderà ai pkgstools del nostro sistema i quali si occuperanno di cercare ed installare le nostre dipendenze.
Prenderemo in esame la versione testing.
Lo spezzone di codice che si occupa di cercare il nostro pacchetto è il seguente:


char*
pkgname(package)
    char *package;
{
    FILE *fp;
    char line[128];
    int count;
    char *pkg = NULL;
    
    if ((fp = fopen("/etc/opm/repository.conf", "r")) == NULL)
        errx(1, "%s", strerror(errno));

    count = 0;
    
    while(fgets(line, sizeof(line), fp) != NULL)
    {
        char* str = strcasestr(line, package);
        
        if (str != NULL)
        {
            count++;
            if(!pkg)
                free(pkg);

            if ((pkg = calloc(strlen(str), sizeof(char))) == NULL)
                errx(1, "%s", strerror(errno));
                
            strlcpy(pkg, str, strlen(str) +1);
        }
        
    }
    
    if (count == 1)
    {
        return pkg;
    }
    else if (count == 0)
    {
        fprintf(stderr,"[E] No packages found !\n");
        exit(-1);
    }
    else
    {
        fprintf(stderr,"[E] %d packages found !\n", count);
        fprintf(stderr,"Use OPM with -s arg to search a package.\n");
        exit(-1);
    }
        
}


Il repository usato (/etc/opm/repository) altro non è se non un LIST del server ftp scelto attraverso la costante FTP dichiarata ad inizio sorgente ed ottenuta attraverso la funzione connection() sfruttante le libcurl:

char*
connection(verbose)
    int verbose;
{
    char *size = NULL;
    CURL *get = NULL;
    CURLcode code;

    /* check OBSDVERS for OpenBSD version */
    
    if(! strcasecmp(got_info(1), "3.9")) {
        
        if ((size = calloc(strlen(FTP) + strlen("/pub/OpenBSD/snapshots/packages/") + strlen(got_info(0)) + strlen("/") + 1, sizeof(char))) == NULL)
            errx(1, "%s", strerror(errno));
            
        strlcpy(size, FTP, strlen(FTP) + 1);
        strncat(size, "/pub/OpenBSD/snapshots/packages/", strlen("/pub/OpenBSD/snapshots/packages/") + 1);
        strncat(size, got_info(0), strlen(got_info(0)) + 1);
        strncat(size, "/", strlen("/") + 1);
        
        *(size + (strlen(FTP) + strlen("/pub/OpenBSD/snapshots/packages/") + strlen(got_info(0)) + strlen("/") + 1)) = '\0';
    
    } else {
        
        if ((size = calloc(strlen(FTP) + strlen("/pub/OpenBSD/") + strlen(got_info(1)) + strlen("/packages/") + strlen(got_info(0)) + strlen("/") + 1, sizeof(char))) == NULL)
            errx(1, "%s", strerror(errno));
            
        strlcpy(size, FTP, strlen(FTP) + 1);
        strncat(size, "/pub/OpenBSD/", strlen("/pub/OpenBSD/") + 1);
        strncat(size, got_info(1), strlen(got_info(1)) + 1);
        strncat(size, "/packages/", strlen("/packages/") + 1);
        strncat(size, got_info(0), strlen(got_info(0)) + 1);
        strncat(size, "/", strlen("/") + 1);
        
        *(size + (strlen(FTP) + strlen("/pub/OpenBSD/") + strlen(got_info(1)) + strlen("/packages/") + strlen(got_info(0)) + strlen("/") + 1)) = '\0';
    }
    
    /* Inizialize FTP connection */
    
    curl_global_init(CURL_GLOBAL_DEFAULT);
    
    if ((get = curl_easy_init()) != NULL) {
        curl_easy_setopt(get, CURLOPT_URL, size);
        curl_easy_setopt(get, CURLOPT_WRITEFUNCTION, file_writing);
        curl_easy_setopt(get, CURLOPT_WRITEDATA, &ftpfile);
        
        if (verbose == 1) //check for verbose mode
            curl_easy_setopt(get, CURLOPT_VERBOSE, 1);
                
        code = curl_easy_perform(get); // FTP connection
        curl_easy_cleanup(get);

        if (code != CURLE_OK) {
            fprintf(stderr, "Connection error\n\n");
            exit(EXIT_FAILURE);
        }
    }
    
    curl_global_cleanup();
    return size;
}

OPM provvederà a parsare la lista alla ricerca del pacchetto da noi selezionato nel ciclo while.
Qualora ci fossero più pacchetti, provvederà a stampare a video la lista di tutti pacchetti installabili sfruttando la funzione search_pkg():

void
search_pkg(pkg)
    char *pkg;
{    
    version();
    fprintf(stdout, "Searching for packages...\n\n");
    
    FILE *fp;
    
    char line[128];
    int count;
    
    if ((fp = fopen("/etc/opm/repository.conf", "r")) == NULL)
        errx(1, "%s", strerror(errno));

    count = 0;
    
    while(fgets(line, sizeof(line), fp) != NULL)
    {
        char* str = strcasestr(line, pkg);
        if (str != NULL)
        {
            if (count == 0)
            {
            fprintf(stdout, "%s",str);
            }
            
            if (count > 1)
            {
                fprintf(stdout, "%s",str);
            }
            
            count++;
        }
    }
    exit(EXIT_SUCCESS);
}

Dall'help fornito (-h) appare evidente che per installare un pacchetto l'argomento da utilizzare è "-I".
Vediamo, quindi, come si svolge l'installazione del pacchetto dnstracer:

# opm -I dnstracer
OpenBSD Packages Manager v.0.1beta
Your OpenBSD version: 3.8

Checking repository...
Package that will be installed is dnstracer-1.8.tgz

Are you sure ? [N|y]y
Installing...
parsing dnstracer-1.8
dnstracer-1.8: complete


Per installare un pacchetto OPM richiama la funzione install_pkg() la quale, a sua volta, riceve il pacchetto dal valore di ritorno della funzione pkgname(), descritta prima:

void
install_pkg(pkg)
    char *pkg;
{
    version();
    char choise[2];
    fprintf(stdout, "Package that will be installed is %s\nAre you sure ? [N|y]", pkgname(pkg));
    scanf("%s", choise);
    if ((strcasecmp(choise, "y") == 0))
    {
        fprintf(stdout, "Installing %s\n", pkgname(pkg));
        char *command = NULL;
        char *url = connection(0);
    
        if ((command = calloc(strlen(url) + strlen(pkgname(pkg)) + strlen("/usr/sbin/pkg_add -v ") + 1, sizeof(char))) == NULL)
            errx(1, "%s", strerror(errno));
            
        strlcpy(command, "/usr/sbin/pkg_add -v ", strlen("/usr/sbin/pkg_add -v ") + 1);
        strncat(command, url, strlen(url) + 1);
        strncat(command, pkgname(pkg), strlen(pkgname(pkg)) + 1);
        *(command + (strlen("/usr/sbin/pkg_add ") + strlen(url) + strlen(pkgname(pkg)) + 1)) = '\0';
        system(command);
        free(url);
        free(command);
    }
    else
    {
            fprintf(stdout, "bye !\n");
            exit(-1);
    }
}


In pieno apt-style avremo il pacchetto comodamente installato sulla nostra OpenBSD box.
Scopriamo le altre possibili opzioni:

# opm -h
OpenBSD Packages Manager v.0.1beta
Your OpenBSD version: 3.8

DESCRIPTION:

OPM is a simple packages manager for OpenBSD.

USAGE:

-h                       this help
-I Pkg_Name              install selected package
-R Pkg_Name              remove selected package
-U                       update the OpenBSD packages repository
-S Pkg_Name              show info about selected package
-V                       show OPM version


L'usabilità del programma è, com'è ben visibile, molto semplice.

Rimozione di un pacchetto:

Per eliminare un software dal nostro sistema il programma si affida all'utility pkg_delete attraverso la funzione remove_pkg():

void
remove_pkg(pkg)
    char *pkg;
{
    char temp_n[15] = "";
    char *t_read;
    FILE *temp_p;
    int fd = -1;
    int count;
    char *choise;
    char toremove[59 + strlen(pkg)];
    
    version();
    
    strlcpy(temp_n, "/etc/opm/temp", sizeof temp_n);
    if ((fd = mkstemp(temp_n)) == -1 || (temp_p = fdopen(fd, "w+")) == NULL)
    {
        
        if (fd != -1)
        {
            unlink(temp_n);
            close(fd);
        }
        
        fprintf(stderr, "%s: %s\n", temp_n, strerror(errno));
        exit(-1);
        
    }
    
    snprintf(toremove, sizeof(toremove), "/bin/ls /var/db/pkg | /usr/bin/grep %s -i > %s", pkg, temp_n);
    system(toremove);
    
    if ((t_read = malloc(40 * sizeof(char))) == NULL)
        errx(1, "%s", strerror(errno));
        
    count = 0;
    
    while ((fgets(t_read, 40, temp_p)) != NULL)
    {
        count++;
    }
    
    if (count == 0)
    {
        fprintf(stdout, "No packages found\n");
        (int)fclose(temp_p);
        (int)remove(temp_n);
        exit(-1);
    }
    
    if (count > 1)
    {
        fprintf(stdout, "There are some results for this search: do you want view all pkgs ? [y|N]");
        scanf("%s", choise);
        
        if ((strcasecmp(choise, "y") == 0))
        {
            FILE *fp;
    
            char line[128];
            int count;
    
            if ((fp = fopen("/etc/opm/temp", "r")) == NULL)
                errx(1, "%s", strerror(errno));
    
            while(fgets(line, sizeof(line), fp) != NULL)
            {
                    fprintf(stdout, "%s",line);
            }

            fprintf(stdout, "\nChoose 1 file to remove and restart OPM with it for -R arg.\n");
        }
        else
        {
            fprintf(stdout, "bye !\n");
        }
        
    }
    else
    {
        fprintf(stdout, "Package that will be deleted is %s\nAre you sure ? [N|y]", t_read);
        scanf("%s", choise);
        
        if ((strcasecmp(choise, "y") == 0))
        {
            char *command = NULL;
            if ((command = calloc(strlen(t_read) + strlen("/usr/sbin/pkg_delete -v ") + 1, sizeof(char))) == NULL)
                errx(1, "%s", strerror(errno));
                
            strlcpy(command, "/usr/sbin/pkg_delete -v ", strlen("/usr/sbin/pkg_delete -v ") + 1);
            strncat(command, t_read, strlen(t_read) + 1);
            
            *(command + (strlen("/usr/sbin/pkg_delete -v ") + strlen(t_read) + 1)) = '\0';
            
            system(command);
        }
        else
        {
            fprintf(stdout, "bye !\n");
        }
    }
    
    (int)fclose(temp_p);
    (int)remove(temp_n);
    exit(EXIT_SUCCESS);
    
}


/etc/opm/temp farà da transito per la lista dei pacchetti selezionati, anche in questo caso, se la ricerca indicizzasse più pacchetti rispetto quanto da noi richiesto il programma si occuperà di printare il tutto a video lasciando all'utente la scelta del pacchetto effettivo da eliminare.

Rimuoviamo quindi il pacchetto precedentemente installato: dnstracer:

# opm -R dnstracer
OpenBSD Packages Manager v.0.1beta
Your OpenBSD version: 3.8

Package that will be deleted is dnstracer-1.8

Are you sure ? [N|y]y
deleting: /usr/local/bin/dnstracer
deleting: /usr/local/man/man8/dnstracer.8***********************               | 77%
dnstracer-1.8: complete


Info Pacchetto:

Per ricevere informazioni circa un pacchetto, OPM sfrutta la funzione info_pkg(), la quale sfrutta pkg_info:

void
info_pkg(pkg)
    char *pkg;
{
    char temp_n[15] = "";
    char *t_read;
    FILE *temp_p;
    int fd = -1;
    int count;
    char *choise;
    char getinfo[59 + strlen(pkg)];
    
    version();
    
    strlcpy(temp_n, "/etc/opm/temp", sizeof temp_n);
    
    if ((fd = mkstemp(temp_n)) == -1 || (temp_p = fdopen(fd, "w+")) == NULL)  //make a temp file for pkg_reading...
    {
        if (fd != -1)
        {
            unlink(temp_n);
            close(fd);
        }
        fprintf(stderr, "%s: %s\n", temp_n, strerror(errno));
         exit(-1);
    }
    
    snprintf(getinfo, sizeof(getinfo), "/bin/ls /var/db/pkg | /usr/bin/grep %s -i > %s", pkg, temp_n);
    system(getinfo);
    
    if ((t_read = malloc(40 * sizeof(char))) == NULL)
        errx(1, "%s", strerror(errno));
        
    count = 0;
    while ((fgets(t_read, 40, temp_p)) != NULL)
    {
        count++;
    }
    
    if (count == 0)
    {
        fprintf(stderr, "No packages found\n");
        (int)fclose(temp_p);
        (int)remove(temp_n);
        exit(-1);
    }
    
    if (count > 1)
    [cut]
    else
    {
        char *command = NULL;
        
        if ((command = calloc(strlen(t_read) + strlen("/usr/sbin/pkg_info ") + 1, sizeof(char))) == NULL)
            errx(1, "%s", strerror(errno));
            
        strlcpy(command, "/usr/sbin/pkg_info ", strlen("/usr/sbin/pkg_info ") + 1);
        strncat(command, t_read, strlen(t_read) + 1);
        
        *(command + (strlen("/usr/sbin/pkg_info ") + strlen(t_read) + 1)) = '\0';
        
        system(command);
    }
    
    (int)fclose(temp_p);
    (int)remove(temp_n);
    
    exit(EXIT_SUCCESS);
    
}


# opm -S irssi-0.8.9
OpenBSD Packages Manager v.0.1beta
Your OpenBSD version: 3.8

Information for irssi-0.8.9

Comment:
modular IRC client with many features (ipv6,socks,proxy)

Required by:
irssi-icb-0.14

Description:
Irssi is a modular IRC client that currently has only text mode user
interface, but 80-90% of the code isn't text mode specific, so other UIs could
be created pretty easily. Also, Irssi isn't really even IRC specific anymore,
there's already a working SILC module available. Support for other protocols
like ICQ could be created some day too.

Flavor: socks support for dante socks firewall implementation

Maintainer: Reinhard J. Sammer <[email protected]>

WWW: http://www.irssi.org/


Concludendo...

OpenBSD Packages Manager ricava le informazioni sulla nostra macchina attraverso la funzione got_info(), tali informazioni vengono usate per scegliere il pacchetto precompilato per la nostra distribuzione e per la nostra architettura:

char*
got_info(opt)
    int opt;
{
    struct utsname up;
    uname(&up);
    char *out;
    if (opt == 1)
    {
        if ((out = calloc(strlen(up.release), sizeof(char))) == NULL)
            errx(1, "%s", strerror(errno));
            
        strlcpy(out, up.release, strlen(up.release) +1);
        *(out + (strlen(up.release) + 1)) = '\0';
        return out;
    }
    else if (opt == 0)
    {
        if ((out = calloc(strlen(up.machine), sizeof(char))) == NULL)
            errx(1, "%s", strerror(errno));
            
        strlcpy(out, up.machine, strlen(up.machine) +1);
        *(out + (strlen(up.machine) + 1)) = '\0';
        return out;
    }
}


L'utilizzo di questo programmino ci semplifica la vita nel momento in cui ci permette di installare un pacchetto in maniera molto agevole, per un prossimo futuro, inoltre, è teorizzabile la comparsa di un'interfaccia GUI, rendendo il tutto ancora più user-friendly.

Buon divertimento!



Privacy Policy