UNIX-Programmierung: Benutzer und Gruppen

Willemers Informatik-Ecke

Ermitteln des Users, der den Prozess startete

Ein Prozess kann erfragen, welcher Benutzer ihn gestartet hat. Die Funktion getuid() liefert die User-ID. Die Funktion geteuid() liefert die effektive User-ID. Diese kann anders lauten, wenn die Programmdatei das SetUID-Bit gesetzt hat. Vergleichbares gibt es für die Gruppe. Dort heißen die Funktionen getgid() und getegid().

#include <unistd.h>

  uid_t getuid(void);
  uid_t geteuid(void);
  gid_t getgid(void);
  gid_t getegid(void);

Die Passwortdatei als Struktur

Soll aus der Nummer der Loginname ermittelt werden, fragt man bei der zentralen Informationsquelle über Benutzer an. Das ist die Datei /etc/passwd. Jede Zeile der Passwortdatei wird in einer Struktur namens passwd abgebildet.

struct passwd {
   char  *pw_name;   /* Benutzername */
   char  *pw_passwd; /* Passwort */
   uid_t pw_uid;     /* User ID */
   gid_t pw_gid;     /* Group ID */
   char  *pw_gecos;  /* Name bzw. GECOS */
   char  *pw_dir;    /* Home-Verzeichnis */
   char  *pw_shell;  /* Loginshell */
};

Ist die User-ID, beispielsweise durch Aufruf von getuid(), oder der Loginname bekannt, kann man den entsprechenden Eintrag mit der Funktion getpwuid() oder getpwnam() holen. Der Rückgabewert ist ein Zeiger auf eine interne Struktur, die beim nächsten Aufruf überschrieben wird.

#include <pwd.h>
#include <sys/types.h>

   struct passwd *getpwnam(const char * name);
   struct passwd *getpwuid(uid_t uid);

Auslesen der Passwortdatei

Um alle Einträge der Passwortdatei auszulesen, gibt es die drei Funktionen setpwent(), getpwent() und endpwent.

#include <pwd.h>
#include <sys/types.h>

   struct passwd *getpwent(void);
   void setpwent(void);
   void endpwent(void);

Mit getpwent() wird sukzessive eine Zeile der Passwortdatei nach der anderen eingelesen. Die Funktion setpwent() öffnet die Datei und setzt den internen Zeiger auf den Anfang und enpwent() schließt die Datei wieder. Um alle Loginnamen der Datei auszulesen, braucht man nur ein recht simples Programm.

#include <pwd.h>

int main()
{
struct passwd *pw;

   setpwent();
   while ( pw = getpwent()) {
      puts(pw->pw_name);
   }
   endpwent();
}

Gruppen

Analog ist das Auslesen der Gruppendatei. Auch hier gibt es eine Struktur, die nach der Datei benannt ist.

struct group {
    char    *gr_name;   /* Gruppenname */
    char    *gr_passwd; /* Gruppenpasswort */
    gid_t   gr_gid;     /* Gruppen-id */
    char    **gr_mem;   /* Gruppenmitglieder */
};

Die Gruppenmitglieder befinden sich im Element gr_mem. Das ist ein Array von Strings. Nach dem letzten Eintrag ist der Zeiger NULL. Auch hier gibt es Funktionen um anhand der ID oder des Namens den entsprechenden Eintrag zu finden. Sie heißen getgrnam() und getgrgid().

#include <grp.h>
#include <sys/types.h>

  struct group *getgrnam(const char *name);
  struct group *getgrgid(gid_t gid);

Auch das Auslesen der group-Datei läuft auf bekannte Weise:

#include <grp.h>
#include <sys/types.h>

  struct group *getgrent(void);
  void setgrent(void);
  void endgrent(void);

Das folgende Beispiel liest die /etc/group aus und listet für jede Gruppe die Mitglieder aus.

#include <grp.h>

int main()
{
struct group *grp;
char *member;
int i;

   setgrent();
   while ( grp = getgrent()) {
      puts(grp->gr_name);
      i = 0;
      member = grp->gr_mem[i++];
      while (member) {
          puts(member);
          member = grp->gr_mem[i++];
      }
      puts("----------------");

   }
   endgrent();
}

Ermitteln aller Gruppen

Ein Prozess kann mit der Funktion getgroups() ermitteln, in welchen Gruppen er angemeldet ist. Dazu bekommt er als Antwort ein Array mit den Group-IDs. Im Beispiel soll mit Hilfe der Funktion getgrgid() die Nummern der Gruppen, in denen der Aufrufer ist und dann der jeweilige Name der Gruppe festgestellt werden und so eine Liste auf dem Bildschirm ausgegeben werden.

#include <grp.h>
#include <limits.h>
#include <sys/types.h>

int main()
{
gid_t grplist[NGROUPS_MAX];
struct group *grp;
char *member;
int i, anzGruppen;

   anzGruppen = getgroups(NGROUPS_MAX, grplist);
   for (i=0; i<anzGruppen; i++) {
      grp = getgrgid(grplist[i]);
      puts(grp->gr_name);
   }
}


Homepage (C) Copyright 2002 Arnold Willemer