controllo e la creazione si ha giusto lo spazio per una \textit{race
condition} (si ricordi quanto visto in \secref{sec:proc_race_cond}).
-Per questo motivo il kernel le \acr{glibc} provvedono una serie di funzioni da
-utilizzare per la gestione dei file temporanei.
+Le \acr{glibc} provvedono varie funzioni per generare nomi di file temporanei,
+di cui si abbia certezza di unicità (al momento della generazione); la prima
+di queste funzioni è \func{tmpnam} il cui prototipo è:
+\begin{prototype}{stdio.h}{char *tmpnam(char *string)}
+ Restituisce il puntatore ad una stringa contente un nome di file valido e
+ non esistente al momento dell'invocazione.
+
+ \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o
+ \macro{NULL} in caso di fallimento. Non sono definiti errori.}
+\end{prototype}
+\noindent se si è passato un puntatore \param{string} non nullo questo deve
+essere di dimensione \macro{L\_tmpnam} (costante definita in \file{stdio.h},
+come \macro{P\_tmpdir} e \macro{TMP\_MAX}) ed il nome generato vi verrà
+copiato automaticamente; altrimenti il nome sarà generato in un buffer statico
+interno che verrà sovrascritto ad una chiamata successiva. Successive
+invocazioni della funzione continueranno a restituire nomi unici fino ad un
+massimo di \macro{TMP\_MAX} volte. Al nome viene automaticamente aggiunto come
+prefisso la directory specificata da \macro{P\_tmpdir}.
+
+Di questa funzione esiste una versione rientrante, \func{tmpnam\_r}, che non
+fa nulla quando si passa \macro{NULL} come parametro. Una funzione simile,
+\func{tempnam}, permette di specificare un prefisso per il file
+esplicitamente, il suo prototipo è:
+\begin{prototype}{stdio.h}{char *tempnam(const char *dir, const char *pfx)}
+ Restituisce il puntatore ad una stringa contente un nome di file valido e
+ non esistente al momento dell'invocazione.
+
+ \bodydesc{La funzione ritorna il puntatore alla stringa con il nome o
+ \macro{NULL} in caso di fallimento, \var{errno} viene settata a
+ \macro{ENOMEM} qualora fallisca l'allocazione della stringa.}
+\end{prototype}
+La funzione alloca con \code{malloc} la stringa in cui resituisce il nome, per
+cui è sempre rientrante, occorre però ricordarsi di disallocare il puntatore
+che restituisce. L'argomento \param{pfx} specifica un prefisso di massimo 5
+caratteri per il nome provvisorio. La funzione assegna come directory per il
+file temporaneo (verificando che esista e sia accessibili), la prima valida
+delle seguenti:
+\begin{itemize*}
+\item La variabile di ambiente \macro{TMPNAME} (non ha effetto se non è
+ definita o se il programma chiamante è \acr{suid} o \acr{sgid}, vedi
+ \secref{sec:file_suid_sgid}).
+\item il valore dell'argomento \param{dir} (se diverso da \macro{NULL}).
+\item Il valore della costante \macro{P\_tmpdir}.
+\item la directory \file{/tmp}.
+\end{itemize*}
+
+In ogni caso, anche se la generazione del nome è casuale, ed è molto difficile
+ottere un nome duplicato, nulla assicura che un altro processo non possa avere
+creato, fra l'ottenimento del nome e l'apertura del file, un altro file con lo
+stesso nome; per questo motivo quando si usa il nome ottenuto da una di queste
+funzioni occorre sempre aprire il nuovo file in modalità di esclusione (cioè
+con l'opzione \macro{O\_EXCL} per i file descriptor o con il flag \code{x} per
+gli stream) che fa fallire l'apertura in caso il file sia già esistente.
+
+Per evitare di dovere effettuare a mano tutti questi controlli, lo standard
+POSIX definisce la funzione \func{tempfile}, il cui prototipo è:
+\begin{prototype}{stdio.h}{FILE *tmpfile (void)}
+ Restituisce un file temporaneo aperto in lettura/scrittura.
+
+ \bodydesc{La funzione ritorna il puntatore allo stream associato al file
+ temporaneo in caso di successo e \macro{NULL} in caso di errore, nel qual
+ caso \var{errno} viene settata a
+ \begin{errlist}
+ \item[\macro{EINTR}] La funzione è stata interrotta da un segnale.
+ \item[\macro{EEXIST}] Non è stato possibile generare un nome univoco.
+ \end{errlist}
+ ed inoltre \macro{EFAULT}, \macro{EMFILE}, \macro{ENFILE}, \macro{ENOSPC},
+ \macro{EROFS} e \macro{EACCESS}.}
+\end{prototype}
+\noindent restituisce direttamente uno stream già aperto (in modalità
+\code{r+b}, si veda \secref{sec:file_fopen}) e pronto per l'uso che viene
+automaticamente cancellato alla sua chiusura o all'uscita dal programma. Lo
+standard non specifica in quale directory verrà aperto il file, ma \acr{glibc}
+prima tentano con \macro{P\_tmpdir} e poi con \file{/tmp}. Questa funzione è
+rientrante e non soffre di problemi di \textit{race condition}.
+
+Alcune versioni meno recenti di Unix non supportano queste funzioni; in questo
+caso si possono usare le vecchie funzioni \func{mktemp} e \func{mkstemp} che
+modificano una stringa di input che serve da modello e che deve essere
+conclusa da 6 caratteri \code{X} che verranno sostituiti da un codice
+unico. La prima delle due è analoga a \func{tmpnam} e genera un nome casuale,
+il suo prototipo è:
+\begin{prototype}{stlib.h}{char *mktemp(char *template)}
+ Genera un filename univoco sostituendo le \code{XXXXXX} finali di
+ \param{template}.
+
+ \bodydesc{La funzione ritorna il puntatore \param{template} in caso di
+ successo e \macro{NULL} in caso di errore, nel qual caso \var{errno} viene
+ settata a:
+ \begin{errlist}
+ \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \end{errlist}}
+\end{prototype}
+\noindent dato che \param{template} deve poter essere modificata dalla
+funzione non si può usare una stringa costante. Tutte le avvertenze riguardo
+alle possibili \textit{race condition} date per \func{tmpnam} continuano a
+valere; inoltre in alcune vecchie implementazioni il valore di usato per
+sostituire le \code{XXXXXX} viene formato con il \acr{pid} del processo più
+una lettera, il che mette a disposizione solo 26 possibilità, e rende il nome
+temporaneo facile da indovinare. Per tutti questi motivi la funzione è
+deprecata e non dovrebbe mai essere usata.
+
+
+
+La seconda funzione, \func{mkstemp} è sostanzialmente equivalente a
+\func{tmpfile}, ma restituisce un file descriptor invece di uno stream; il suo
+prototipo è:
+\begin{prototype}{stlib.h}{int mkstemp(char *template)}
+ Genera un file temporaneo con un nome ottenuto sostituendo le \code{XXXXXX}
+ finali di \param{template}.
+
+ \bodydesc{La funzione ritorna il file descriptor in caso successo e
+ -1 in caso di errore, nel qual caso \var{errno} viene settata a:
+ \begin{errlist}
+ \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \item[\macro{EEXIST}] non è riuscita a creare un file temporano, il
+ contenuto di \param{template} è indefinito.
+ \end{errlist}}
+\end{prototype}
+\noindent come per \func{mktemp} \param{template} non può essere una stringa
+costante. La funzione apre un file in lettura/scrittura con la funzione
+\func{open}, usando l'opzione \macro{O\_EXCL} (si veda
+\secref{sec:file_open}), in questo modo al ritorno della funzione si ha la
+certezza di essere i soli utenti del file. I permessi sono settati al valore
+\code{0600}\footnote{questo è vero a partire dalle \acr{glibc} 2.0.7, le
+ versioni precedenti delle \acr{glibc} e le vecchie \acr{libc5} e \acr{libc4}
+ usavano il valore \code{0666} che permetteva a chiunque di leggere i
+ contenuti del file.} (si veda \secref{sec:file_perm_overview}).
+
+In OpenBSD è stata introdotta un'altra funzione\footnote{introdotta anche in
+ Linux a partire dalle \acr{glibc} 2.1.91.} simile alle precedenti,
+\func{mkdtemp}, che crea una directory temporanea; il suo prototipo è:
+\begin{prototype}{stlib.h}{char *mkdtemp(char *template)}
+ Genera una directory temporaneo il cui nome è ottenuto sostituendo le
+ \code{XXXXXX} finali di \param{template}.
+
+ \bodydesc{La funzione ritorna il puntatore al nome della directory in caso
+ successo e \macro{NULL} in caso di errore, nel qual caso \var{errno} viene
+ settata a:
+ \begin{errlist}
+ \item[\macro{EINVAL}] \param{template} non termina con \code{XXXXXX}.
+ \end{errlist}
+ più gli altri eventuali codici di errore di \func{mkdir}.}
+\end{prototype}
+\noindent la directory è creata con permessi \code{0700} (al solito si veda
+\capref{cha:file_unix_interface} per i dettagli); dato che la creazione della
+directory è sempre esclusiva i precedenti problemi di \textit{race condition}
+non si pongono.
\section{La manipolazione delle caratteristiche dei files}
\label{sec:file_chroot}
Benché non abbia niente a che fare con permessi, utenti e gruppi, questa
-funzione viene usata spesso per limitare le capacità dei programmi, ed è
-pertanto pertinente al controllo di accesso. Come accennato in
-\secref{sec:proc_fork} ogni processo oltre ad una directory di lavoro
-corrente, ha anche una directory radice, cioè una directory che per il
-processo costituisce la radice dell'albero del filesystem.
+funzione viene usata spesso per restringere le capacità di acccesso di un
+programma ad una sezione limitata del filesystem, per cui ne parleremo in
+questa sezione.
+
+Come accennato in \secref{sec:proc_fork} ogni processo oltre ad una directory
+di lavoro corrente, ha anche una directory radice, cioè una directory che per
+il processo costituisce la radice dell'albero del filesystem. Questa viene
+eredidata dal padre per ogni processo figlio, (come si può vedere da
+\figref{fig:proc_task_struct} è tenuta nella struttura \type{fs\_struct}
+insieme alla directory di lavoro corrente e alla \var{umask}) e quindi di
+norma coincide con la \file{/} del sistema.
+
+In certe situazioni però per motivi di sicurezza non si vuole che un processo
+possa accedere a tutto il filesystem; per questo si può cambiare la directory
+radice con la funzione \func{chroot}, il cui prototipo è:
+\begin{prototype}{unistd.h}{int chroot(const char *path)}
+ Cambia la directory radice del processo a quella specificata da
+ \param{path}..
+
+\bodydesc{La funzione restituisce zero in caso di successo e -1 per
+ un errore, in caso di errore \texttt{errno} viene settato ai valori:
+ \begin{errlist}
+ \item[\macro{EPERM}] L'\textit{effective user id} non è zero.
+ \end{errlist}
+ ed inoltre \macro{EFAULT}, \macro{ENAMETOOLONG}, \macro{ENOENT},
+ \macro{ENOMEM}, \macro{ENOTDIR}, \macro{EACCES}, \macro{ELOOP};
+ \macro{EROFS} e \macro{EIO}.}
+\end{prototype}
+
+
+
+
+
+un caso tipico è quello di un server
+ftp che dovrebbe limitarsi
+
-In generale questa directory coincide con la
+Il sistema però consente di cambiare questa directory con la funzione
+\func{chroot}
gestione.
-\subsection{La gerarchia dei processi}
+\subsection{L'architettura della gestione dei processi}
\label{sec:proc_hierarchy}
A differenza di quanto avviene in altri sistemi (ad esempio nel VMS la
alla cui base c'è \cmd{init} che è progenitore di tutti gli altri processi.
-\subsection{Una panoramica sulle funzioni di gestione}
+Il kernel mantiene una tabella dei processi attivi, la cosiddetta
+\textit{process table}; per ciascun processo viene mantenuta una voce nella
+tabella dei processi costituita da una struttura \type{task\_struct}, che
+contiene tutte le informazioni rilevanti per quel processo. Tutte le strutture
+usate a questo scopo sono dichiarate nell'header file \file{linux/sched.h}, ed
+uno schema semplificato che riporta la struttura delle principali informazioni
+contenute nella \type{task\_struct} (che in seguito incontreremo a più
+riprese), è mostrato in \nfig.
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=13cm]{img/task_struct}
+ \caption{Schema semplificato dell'architettura delle strutture usate dal
+ kernel nella gestione dei processi.}
+ \label{fig:proc_task_struct}
+\end{figure}
+
+
+Come accennato in \secref{sec:intro_unix_struct} è lo \textit{scheduler} che
+decide quale processo mettere in esecuzione; esso viene eseguito ad ogni
+system call ed ad ogni interrupt, (ma può essere anche attivato
+esplicitamente). Il timer di sistema provvede comunque a che esso sia invocato
+periodicamente, generando un interrupt periodico secondo la frequenza
+specificata dalla costante \macro{HZ}, definita in \file{asm/param.h} Il
+valore usuale è 100 (è espresso in Hertz), si ha cioè un interrupt dal timer
+ogni centesimo di secondo.
+
+Ogni volta che viene eseguito, lo \textit{scheduler} effettua il calcolo delle
+priorità dei vari processi attivi (torneremo su questo in
+\secref{sec:proc_priority}) e stabilisce quale di essi debba essere posto in
+esecuzione fino alla successiva invocazione.
+
+
+\subsection{Una panoramica sulle funzioni fondamentali}
\label{sec:proc_handling_intro}
I processi vengono creati dalla funzione \func{fork}; in molti unix questa è
-\section{La gestione dei processi}
+\section{Le funzioni di base}% della gestione dei processi}
\label{sec:proc_handling}
In questa sezione tratteremo le problematiche della gestione dei processi
all'interno del sistema, illustrandone tutti i dettagli. Inizieremo con le
funzioni elementari che permettono di leggerne gli identificatori, per poi
-passare alla spiegazione delle funzioni fondamentali che si usano per la
-creazione e la terminazione dei processi, e per la messa in esecuzione degli
-altri programmi.
+passare alla spiegazione delle funzioni base che si usano per la creazione e
+la terminazione dei processi, e per la messa in esecuzione degli altri
+programmi.
\subsection{Gli identificatori dei processi}
\item gli identificatori per il controllo di sessione: il \textit{process
group id} e il \textit{session id} ed il terminale di controllo (vedi
\secref{sec:sess_xxx} e \secref{sec:sess_xxx}).
-\item i flag di \acr{suid} e \acr{sgid} (vedi \secref{sec:file_suid_sgid}).
+\item gli identificatori per il controllo di accesso (vedi
+ \secref{sec:proc_user_group}).
\item la directory di lavoro e la directory radice (vedi
\secref{sec:file_work_dir} e \secref{sec:file_chroot}).
\item la maschera dei permessi di creazione (vedi \secref{sec:file_umask}).
Sospende il processo corrente finché un figlio non è uscito, o finché un
segnale termina il processo o chiama una funzione di gestione.
-\bodydesc{
-La funzione restituisce il \acr{pid} del figlio in caso di successo e -1 in
-caso di errore; \var{errno} può assumere i valori:
+\bodydesc{La funzione restituisce il \acr{pid} del figlio in caso di successo
+ e -1 in caso di errore; \var{errno} può assumere i valori:
\begin{errlist}
\item[\macro{EINTR}] la funzione è stata interrotta da un segnale.
- \end{errlist}
-}
+ \end{errlist}}
\end{functions}
\noindent
è presente fin dalle prime versioni di unix; la funzione ritorna non appena un
\end{functions}
\noindent
la struttura \type{rusage} è definita in \file{sys/resource.h}, e viene
-utilizzata anche dalla funzione \func{getrusage} per ottenere le risorse di
-sistema usate dal processo; la sua definizione è riportata in \nfig.
-\begin{figure}[!htb]
- \footnotesize
- \centering
- \begin{minipage}[c]{15cm}
- \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct rusage {
- struct timeval ru_utime; /* user time used */
- struct timeval ru_stime; /* system time used */
- long ru_maxrss; /* maximum resident set size */
- long ru_ixrss; /* integral shared memory size */
- long ru_idrss; /* integral unshared data size */
- long ru_isrss; /* integral unshared stack size */
- long ru_minflt; /* page reclaims */
- long ru_majflt; /* page faults */
- long ru_nswap; /* swaps */
- long ru_inblock; /* block input operations */
- long ru_oublock; /* block output operations */
- long ru_msgsnd; /* messages sent */
- long ru_msgrcv; /* messages received */
- long ru_nsignals; ; /* signals received */
- long ru_nvcsw; /* voluntary context switches */
- long ru_nivcsw; /* involuntary context switches */
-};
- \end{lstlisting}
- \end{minipage}
- \normalsize
- \caption{La struttura \var{rusage} per la lettura delle informazioni dei
- delle risorse usate da un processo.}
- \label{fig:proc_rusage_struct}
-\end{figure}
+utilizzata anche dalla funzione \func{getrusage} (vedi \secref{sec:sys_xxx})
+per ottenere le risorse di sistema usate dal processo; la sua definizione è
+riportata in \figref{fig:sys_rusage_struct}.
In genere includere esplicitamente \file{<sys/time.h>} non è più
necessario, ma aumenta la portabilità, e serve in caso si debba accedere
\func{exec} assume anche una serie di altre proprietà del processo chiamante;
la lista completa è la seguente:
\begin{itemize*}
-\item il \textit{process ID} (\acr{pid}) ed il \textit{parent process ID}
+\item il \textit{process id} (\acr{pid}) ed il \textit{parent process id}
(\acr{ppid}).
-\item il \textit{real user ID} ed il \textit{real group ID} (vedi
+\item il \textit{real user id} ed il \textit{real group id} (vedi
\secref{sec:proc_user_group}).
-\item i \textit{supplementary group ID} (vedi \secref{sec:proc_user_group}).
-\item il \textit{session ID} ed il \textit{process group ID} (vedi
+\item i \textit{supplementary group id} (vedi \secref{sec:proc_user_group}).
+\item il \textit{session id} ed il \textit{process group id} (vedi
\secref{sec:sess_xxx}).
\item il terminale di controllo (vedi \secref{sec:sess_xxx}).
\item il tempo restante ad un allarme (vedi \secref{sec:sig_xxx}).
settaggio del flag di \textit{close-on-exec} sulle directory che apre, in
maniera trasparente all'utente.
-Abbiamo detto che il \textit{real user ID} ed il \textit{real group ID}
+Abbiamo detto che il \textit{real user id} ed il \textit{real group id}
restano gli stessi all'esecuzione di \func{exec}; lo stesso vale per
-l'\textit{effective user ID} ed l'\textit{effective group ID}, tranne il caso
+l'\textit{effective user id} ed l'\textit{effective group id}, tranne il caso
in cui il file che si va ad eseguire ha o il \acr{suid} bit o lo \acr{sgid}
-bit settato, nel qual caso \textit{effective user ID} e \textit{effective
- group ID} vengono settati rispettivamente all'utente o al gruppo cui il file
+bit settato, nel qual caso \textit{effective user id} e \textit{effective
+ group id} vengono settati rispettivamente all'utente o al gruppo cui il file
appartiene (per i dettagli vedi \secref{sec:proc_perms}).
Se il file da eseguire è in formato \emph{a.out} e necessita di librerie
\label{tab:proc_uid_gid}
\end{table}
-Al primo gruppo appartengono il \textit{real user ID} e il \textit{real group
- ID}: questi vengono settati al login ai valori corrispondenti all'utente con
+Al primo gruppo appartengono il \textit{real user id} e il \textit{real group
+ id}: questi vengono settati al login ai valori corrispondenti all'utente con
cui si accede al sistema (e relativo gruppo di default). Servono per
l'identificazione dell'utente e normalmente non vengono mai cambiati. In
realtà vedremo (in \secref{sec:proc_setuid}) che è possibile modificarli, ma
procedura di autenticazione lancia una shell per la quale setta questi
identificatori ai valori corrispondenti all'utente che entra nel sistema.
-Al secondo gruppo appartengono l'\textit{effective user ID} e
-l'\textit{effective group ID} (a cui si aggiungono gli eventuali
+Al secondo gruppo appartengono l'\textit{effective user id} e
+l'\textit{effective group id} (a cui si aggiungono gli eventuali
\textit{supplementary group id} dei gruppi dei quale l'utente fa parte).
Questi sono invece gli identificatori usati nella verifiche dei permessi del
processo e per il controllo di accesso ai file (argomento affrontato in
\begin{functions}
\headdecl{unistd.h}
\headdecl{sys/types.h}
- \funcdecl{uid\_t getuid(void)} Restituisce il \textit{real user ID} del
+ \funcdecl{uid\_t getuid(void)} Restituisce il \textit{real user id} del
processo corrente.
- \funcdecl{uid\_t geteuid(void)} Restituisce l'\textit{effective user ID} del
+ \funcdecl{uid\_t geteuid(void)} Restituisce l'\textit{effective user id} del
processo corrente.
- \funcdecl{gid\_t getgid(void)} Restituisce il \textit{real group ID} del
+ \funcdecl{gid\_t getgid(void)} Restituisce il \textit{real group id} del
processo corrente.
- \funcdecl{gid\_t getegid(void)} Restituisce l'\textit{effective group ID} del
+ \funcdecl{gid\_t getegid(void)} Restituisce l'\textit{effective group id} del
processo corrente.
\bodydesc{Queste funzioni non riportano condizioni di errore.}
\headdecl{sys/types.h}
\funcdecl{int setreuid(uid\_t ruid, uid\_t euid)} Setta il \textit{real user
- ID} e l'\textit{effective user ID} del processo corrente ai valori
+ id} e l'\textit{effective user id} del processo corrente ai valori
specificati da \var{ruid} e \var{euid}.
\funcdecl{int setregid(gid\_t rgid, gid\_t egid)} Setta il \textit{real group
- ID} e l'\textit{effective group ID} del processo corrente ai valori
+ id} e l'\textit{effective group id} del processo corrente ai valori
specificati da \var{rgid} e \var{egid}.
\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
\textit{saved id} viene sempre settato al valore dell'\textit{effective id}.
+
+\subsection{Le funzioni \func{seteuid} e \func{setegid}}
+\label{sec:proc_seteuid}
+
+Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque
+supportate dalla maggior parte degli Unix) e usate per cambiare gli
+\textit{effective id}; i loro prototipi sono:
+\begin{functions}
+\headdecl{unistd.h}
+\headdecl{sys/types.h}
+
+\funcdecl{int seteuid(uid\_t uid)} Setta l'\textit{effective user id} del
+processo corrente a \var{uid}.
+
+\funcdecl{int setegid(gid\_t gid)} Setta l'\textit{effective group id} del
+processo corrente a \var{gid}.
+
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
+ di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\end{functions}
+
+Gli utenti normali possono settare l'\textit{effective id} solo al valore del
+\textit{real id} o del \textit{saved id}, l'amministratore può specificare
+qualunque valore. Queste funzioni sono usate per permettere a root di settare
+solo l'\textit{effective id}, dato che l'uso normale di \func{setuid} comporta
+il settaggio di tutti gli identificatori.
+
+
\subsection{Le funzioni \func{setresuid} e \func{setresgid}}
\label{sec:proc_setresuid}
\headdecl{sys/types.h}
\funcdecl{int setresuid(uid\_t ruid, uid\_t euid, uid\_t suid)} Setta il
-\textit{real user ID}, l'\textit{effective user ID} e il \textit{saved user
- ID} del processo corrente ai valori specificati rispettivamente da
+\textit{real user id}, l'\textit{effective user id} e il \textit{saved user
+ id} del processo corrente ai valori specificati rispettivamente da
\var{ruid}, \var{euid} e \var{suid}.
\funcdecl{int setresgid(gid\_t rgid, gid\_t egid, gid\_t sgid)} Setta il
-\textit{real group ID}, l'\textit{effective group ID} e il \textit{saved group
- ID} del processo corrente ai valori specificati rispettivamente da
+\textit{real group id}, l'\textit{effective group id} e il \textit{saved group
+ id} del processo corrente ai valori specificati rispettivamente da
\var{rgid}, \var{egid} e \var{sgid}.
\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
valori che vuole; un valore di -1 per un qualunque parametro lascia inalterato
l'identificatore corrispondente.
-
-
-\subsection{Le funzioni \func{seteuid} e \func{setegid}}
-\label{sec:proc_seteuid}
-
-Queste funzioni sono un'estensione allo standard POSIX.1 (ma sono comunque
-supportate dalla maggior parte degli Unix) e usate per cambiare gli
-\textit{effective id}; i loro prototipi sono:
+Per queste funzioni esistono anche due controparti che permettono di leggere
+in blocco i vari identificatori: \func{getresuid} e \func{getresgid}; i loro
+prototipi sono:
\begin{functions}
\headdecl{unistd.h}
\headdecl{sys/types.h}
-\funcdecl{int seteuid(uid\_t uid)} Setta l'\textit{effective user ID} del
-processo corrente a \var{uid}.
-
-\funcdecl{int setegid(gid\_t gid)} Setta l'\textit{effective group ID} del
-processo corrente a \var{gid}.
+\funcdecl{int getresuid(uid\_t *ruid, uid\_t *euid, uid\_t *suid)} Legge il
+\textit{real user id}, l'\textit{effective user id} e il \textit{saved user
+ id} del processo corrente.
+
+\funcdecl{int getresgid(gid\_t *rgid, gid\_t *egid, gid\_t *sgid)} Legge il
+\textit{real group id}, l'\textit{effective group id} e il \textit{saved group
+ id} del processo corrente.
-\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
- di fallimento: l'unico errore possibile è \macro{EPERM}.}
+\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+ fallimento: l'unico errore possibile è \macro{EFAULT} se gli indirizzi delle
+ variabili di ritorno non sono validi.}
\end{functions}
-Gli utenti normali possono settare l'\textit{effective id} solo al valore del
-\textit{real id} o del \textit{saved id}, l'amministratore può specificare
-qualunque valore. Queste funzioni sono usate per permettere a root di settare
-solo l'\textit{effective id}, dato che l'uso normale di \func{setuid} comporta
-il settaggio di tutti gli identificatori.
-
+Anche queste funzioni sono una estensione specifica di Linux, e non richiedono
+nessun privilegio. I valori sono restituiti negli argomenti, che vanno
+specificati come puntatori (è un'altro esempio di \textit{value result
+ argument}). Si noti che queste funzioni sono le uniche in grado di leggere i
+\textit{saved id}.
+
\subsection{Le funzioni \func{setfsuid} e \func{setfsgid}}
\label{sec:proc_setfsuid}
\begin{functions}
\headdecl{sys/fsuid.h}
-\funcdecl{int setfsuid(uid\_t fsuid)} Setta il \textit{filesystem user ID} del
+\funcdecl{int setfsuid(uid\_t fsuid)} Setta il \textit{filesystem user id} del
processo corrente a \var{fsuid}.
-\funcdecl{int setfsgid(gid\_t fsgid)} Setta l'\textit{filesystem group ID} del
+\funcdecl{int setfsgid(gid\_t fsgid)} Setta l'\textit{filesystem group id} del
processo corrente a \var{fsgid}.
\bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso
coincide con uno dei \textit{real}, \textit{effective} o \textit{saved id}.
+\subsection{Le funzioni \func{setgroups} e \func{getgroups}}
+\label{sec:proc_setgroups}
+
+Le ultime funzioni che esamineremo sono quelle sono quelle che permettono di
+operare sui gruppi supplementari. Ogni processo può avere fino a
+\macro{NGROUPS\_MAX} gruppi supplementari in aggiunta al gruppo primario,
+questi vengono ereditati dal processo padre e possono essere cambiati con
+queste funzioni.
+
+La funzione che permette di leggere i gruppi supplementari è \func{getgroups};
+questa funzione è definita nello standard POSIX ed il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{unistd.h}
+
+ \funcdecl{int getgroups(int size, gid\_t list[])} Legge gli identificatori
+ dei gruppi supplementari del processo sul vettore \param{list} di dimensione
+ \param{size}.
+
+ \bodydesc{La funzione restituisce il numero di gruppi letti in caso di
+ successo e -1 in caso di fallimento, nel qual caso \var{errno} viene
+ settata a:
+ \begin{errlist}
+ \item[\macro{EFAULT}] \param{list} non ha un indirizzo valido.
+ \item[\macro{EINVAL}] il valore di \param{size} è diverso da zero ma
+ minore del numero di gruppi supplementari del processo.
+ \end{errlist}}
+\end{functions}
+\noindent non è specificato se la funzione inserisca o meno nella lista
+l'\textit{effective user id} del processo. Se si specifica un valore di
+\param{size} uguale a 0 \param{list} non viene modificato, ma si ottiene il
+numero di gruppi supplementari.
+
+Una seconda funzione, \func{getgrouplist}, può invece essere usata per
+ottenere tutti i gruppi a cui appartiene un utente; il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{grp.h}
+
+ \funcdecl{int getgrouplist(const char *user, gid\_t group, gid\_t *groups,
+ int *ngroups)} Legge i gruppi supplementari dell'utente \param{user}.
+
+ \bodydesc{La funzione legge fino ad un massimo di \param{ngroups} valori,
+ restituisce 0 in caso di successo e -1 in caso di fallimento.}
+\end{functions}
+\noindent la funzione esegue una scansione del database dei gruppi (si veda
+\secref{sec:sys_xxx}) e ritorna in \param{groups} la lista di quelli a cui
+l'utente appartiene. Si noti che \param{ngroups} è passato come puntatore
+perché qualora il valore specificato sia troppo piccolo la funzione ritorna -1
+e passando indietro il numero dei gruppi trovati.
+
+Per settare i gruppi supplementari di un processo ci sono due funzioni, che
+possono essere usate solo se si hanno i privilegi di amministratore. La prima
+delle due è \func{setgroups}, ed il suo prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{grp.h}
+
+ \funcdecl{int setgroups(size\_t size, gid\_t *list)} Setta i gruppi
+ supplementari del processo ai valori specificati in \param{list}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ fallimento, nel qual caso \var{errno} viene settata a:
+ \begin{errlist}
+ \item[\macro{EFAULT}] \param{list} non ha un indirizzo valido.
+ \item[\macro{EPERM}] il processo non ha i privilegi di amministratore.
+ \item[\macro{EINVAL}] il valore di \param{size} è maggiore del valore
+ massimo (\macro{NGROUPS}, che per Linux è 32).
+ \end{errlist}}
+\end{functions}
+
+Se invece si vogliono settare i gruppi supplementari del processo a quelli di
+un utente specifico si può usare \func{initgroups} il cui prototipo è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{grp.h}
+
+ \funcdecl{int initgroups(const char *user, gid\_t group)} Setta i gruppi
+ supplementari del processo a quelli di cui è membro l'utente \param{user},
+ aggiungendo il gruppo addizionale \param{group}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ fallimento, nel qual caso \var{errno} viene settata agli stessi valori di
+ \func{setgroups} più \macro{ENOMEM} quando non c'è memoria sufficiente per
+ allocare lo spazio per informazioni dei gruppi.}
+\end{functions}
+
+La funzione esegue la scansione del database dei gruppi (usualmente
+\file{/etc/groups}) cercando i gruppi di cui è membro \param{user} costruendo
+una lista di gruppi supplementari a cui aggiunge \param{group}, che poi setta
+usando \func{setgroups}.
+
+Si tenga presente che sia \func{setgroups} che \func{initgroups} non sono
+definite nello standard POSIX.1 e che pertanto non è possibile utilizzarle
+quando si definisce \macro{\_POSIX\_SOURCE} o si compila con il flag
+\cmd{-ansi}.
+
+
+\section{La gestione della priorità di esecuzione}
+\label{sec:proc_priority}
+
+In questa sezione tratteremo più approfonditamente i meccanismi con il quale
+lo \textit{scheduler} assegna la CPU ai vari processi attivi, illustrando le
+varie funzioni che permettono di leggere e modificare le priorità di
+esecuzione dei programmi.
+
+
+
+
+
\section{Problematiche di programmazione multitasking}
\label{sec:proc_multi_prog}
Benché i processi siano strutturati in modo da apparire il più possibile come
-indipendenti l'uno dall'altro, nella programmazione in un sistema multiutente
-occorre tenere conto di tutta una serie di problematiche che normalmente non
+indipendenti l'uno dall'altro, nella programmazione in un sistema multitasking
+occorre tenere conto di una serie di problematiche che normalmente non
esistono quando si ha a che fare con un sistema in cui viene eseguito un solo
-programma alla volta.
+programma alla volta.
-Pur non essendo tutto questo direttamente legato alla modalità specifica in
-cui il multitasking è implementato in un sistema unix-like, né al solo
-concetto di multitasking (le stesse problematiche si presentano ad esempio
-nella gestione degli interrupt hardware), in questa sezione conclusiva del
-capitolo in cui abbiamo affrontato la gestione dei processi, introdurremo
-sinteticamente queste problematiche, che ritroveremo a più riprese in capitoli
-successivi, con una breve definizione della terminologia e delle loro
-caratteristiche di fondo.
+Pur essendo questo argomento di carattere generale, in questa sezione
+conclusiva del capitolo in cui abbiamo affrontato la gestione dei processi ci
+è parso opportuno introdurre sinteticamente queste problematiche, che
+ritroveremo a più riprese in capitoli successivi, dando una breve descrizione
+delle loro caratteristiche principali e della terminologia relativa.
\subsection{Le operazioni atomiche}
\code{\_r} al nome della versione normale.
-
-