home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.bin / SourceCode / libcs / getname.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-11  |  7.4 KB  |  241 lines

  1. /*
  2.  * Copyright (c) 1990 Carnegie Mellon University
  3.  * All Rights Reserved.
  4.  * 
  5.  * Permission to use, copy, modify and distribute this software and its
  6.  * documentation is hereby granted, provided that both the copyright
  7.  * notice and this permission notice appear in all copies of the
  8.  * software, derivative works or modified versions, and any portions
  9.  * thereof, and that both notices appear in supporting documentation.
  10.  *
  11.  * THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY
  12.  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  13.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT
  14.  * SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT,
  15.  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  17.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  *
  20.  * Users of this software agree to return to Carnegie Mellon any
  21.  * improvements or extensions that they make and grant Carnegie the
  22.  * rights to redistribute these changes.
  23.  *
  24.  * Export of this software is permitted only after complying with the
  25.  * regulations of the U.S. Deptartment of Commerce relating to the
  26.  * Export of Technical Data.
  27.  */
  28. /*
  29.  * This file contains the code for the following getname routine:
  30.  *
  31.  * getname:
  32.  *    purpose:
  33.  *        getname returns the user from the password file
  34.  *        associated with a specified user-id. The user-id
  35.  *        is passed as an integer parameter to the routine.
  36.  *
  37.  *    If a user whose id matches the parameter uid is found in the
  38.  *    password file, the name corresponding to that user is returned.
  39.  *    If no match is found, NULL is returned.  If malloc() fails,
  40.  *    NULL is returned.  If id is -1, all allocated memory is freed.
  41.  *
  42.  *    During the search for a particular user-id, a hash table names
  43.  *    is built for storing user-id's and their corresponding names
  44.  *    from the password file. When the routine is first called, entries
  45.  *    are read from the password file until a match for uid, or the
  46.  *    end of the password file, is found. Any entries not matching uid
  47.  *    and not already stored in the names structure are then stored in
  48.  *    names.
  49.  *
  50.  *    On subsequent calls to getname, the structure names is checked
  51.  *    first for a match for uid. If no match is found, and  if the entire
  52.  *    password file has not been stored, entries from it are stored in
  53.  *    names as before.
  54.  *
  55.  *    When the entire password file has been stored, only names
  56.  *    is checked for a matching user-id on subsequent calls to getname.
  57.  **********************************************************************
  58.  * HISTORY
  59.  * $Log:    getname.c,v $
  60.  * Revision 1.2  90/12/11  17:54:56  mja
  61.  *     Add copyright/disclaimer for distribution.
  62.  * 
  63.  * 25-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  64.  *    Ran through lint and fixed bad routine calls and returns.  Added
  65.  *    register variables where apropriate.  Added code to detect malloc
  66.  *    failures.  Added special call value (-1) to free hash table for
  67.  *    cleaning up allocated memory.
  68.  *
  69.  **********************************************************************
  70.  */
  71.  
  72. #include <pwd.h>            /* passwd struct include file */
  73. #include <utmp.h>            /* utmp struct include file */
  74. #include <stdio.h>
  75.  
  76. #define HASHBITS 6            /* number of bits to hash */
  77. #define HASHSIZE (1<<HASHBITS)        /* limit on the number of buckets
  78.                        in the hash table */
  79. #define HASHMASK (HASHSIZE-1)        /* mask of bits to hash */
  80. #define hash(uid) ((uid)&HASHMASK)    /* determines in which of the HASHSIZE
  81.                        buckets uid would belong */
  82. static struct utmp ut;
  83. #define NMAX (sizeof ut.ut_name)    /* maximum length for a name */
  84.  
  85. /* struct for storing an entry of the hash table */
  86. struct entry {
  87.     char a_name[NMAX+1];        /* stores the name of the user  */
  88.     int a_uid;            /* stores the uid of the user   */
  89.     struct entry *next;        /* stores the pointer to the
  90.                        next entry of the hash table */
  91. };
  92.  
  93. static struct entry *names[HASHSIZE];    /* the hash table of users */
  94.  
  95. /* returns the entry of names that stores the user of id uid if
  96.    one exists in names, else NULL is returned */
  97. static struct entry *inset(uid)
  98.     register int uid;
  99. {
  100.     register struct entry *temp;
  101.  
  102.     for (temp = names[hash(uid)]; temp != NULL; temp = temp->next)
  103.         if (temp->a_uid == uid)
  104.             return(temp);
  105.     return(NULL);
  106. }
  107.  
  108. /* allocates space for an entry in names, setting next field to NULL */
  109. static struct entry *make_blank_entry()
  110. {
  111.     register struct entry *blank_entry;
  112.  
  113.     blank_entry = (struct entry*)(malloc(sizeof(struct entry)));
  114.     if (blank_entry == NULL)
  115.         return(NULL);
  116.     blank_entry->next = NULL;
  117.     return(blank_entry);
  118. }
  119.  
  120. /* inserts a blank entry into the correct position of names for a user
  121.    whose id is uid */
  122. static struct entry *place_blank_entry(uid)
  123.     register int uid;
  124. {
  125.     register struct entry **temp;
  126.     struct entry *make_blank_entry();
  127.  
  128.     temp = &names[hash(uid)];
  129.     while (*temp != NULL)
  130.         temp = &((*temp)->next);
  131.     return(*temp = make_blank_entry());
  132. }
  133.  
  134. /* inserts the data of an entry from the password file (stored in pw_entry)
  135.    into an entry of names (the parameter blank_entry) */
  136. static fill_in(blank_entry, pw_entry)
  137.     register struct entry *blank_entry;
  138.     register struct passwd *pw_entry;
  139. {
  140.     strncpy(blank_entry->a_name, pw_entry->pw_name, NMAX);
  141.     blank_entry->a_name[NMAX] = '\0';
  142.     blank_entry->a_uid = pw_entry->pw_uid;
  143. }
  144.  
  145. /* creates an entry in names storing the data of an entry from the
  146.    password file which stored in the paramter passwd_entry */
  147. static struct entry *create_names_entry(passwd_entry)
  148.     register struct passwd *passwd_entry;
  149. {
  150.     register struct entry *new_entry;
  151.     struct entry *place_blank_entry();
  152.  
  153.     new_entry = place_blank_entry(passwd_entry->pw_uid);
  154.     if (new_entry == NULL)
  155.         return(NULL);
  156.     fill_in(new_entry, passwd_entry);
  157.     return(new_entry);
  158. }
  159.  
  160. /* initializes hash table */
  161. static set_hash_table()
  162. {
  163.     register int i;
  164.  
  165.     for (i = 0; i < HASHSIZE; i++)
  166.         names[i] = NULL;
  167. }
  168.  
  169. /* free hash table */
  170. static free_hash_table()
  171. {
  172.     register int i;
  173.     register struct entry *temp;
  174.  
  175.     for (i = 0; i < HASHSIZE; i++)
  176.         while ((temp = names[i]) != NULL) {
  177.             names[i] = temp->next;
  178.             free((char *)temp);
  179.         }
  180. }
  181.  
  182. /* returns the name of the user in the passwords file whose id is uid.
  183.    NULL is returned if none exists */
  184. char *getname(uid)
  185. register uid;
  186. {
  187.     register struct passwd *pw;    /* pre-defined struct */
  188.     static init;            /* indicates status of the password file
  189.                         0 = file unopen
  190.                         1 = file open
  191.                         2 = file entirely read
  192.                      */
  193.     /* pre-defined routines for accessing the password routine */
  194.     struct passwd *getpwent();
  195.     int setpwent();
  196.     int endpwent();
  197.  
  198.     struct entry *inset();
  199.     register struct entry *Location;
  200.  
  201.     if (uid == -1) {
  202.         if (init != 0)
  203.             free_hash_table();
  204.         if (init == 1)
  205.             endpwent();
  206.         init = 0;
  207.         return(NULL);
  208.     }
  209.  
  210.     if (init == 0) {
  211.         set_hash_table();
  212.         setpwent();
  213.         init = 1;
  214.     }
  215.  
  216.     Location = inset(uid);        /* check if user is in names */
  217.     if (Location != NULL)
  218.         return(Location->a_name); /* user already stored in names */
  219.     if (init == 2)
  220.         return(NULL);        /* entire password file has been
  221.                        stored in names */
  222.  
  223.        /* continue reading entries from the password file, storing any in
  224.       names whose uid is not already located in names, stopping when
  225.       a match is found for the uid or the entire password file has
  226.       been stored */
  227.  
  228.     while ((pw = getpwent()) != NULL) {
  229.         Location = inset(pw->pw_uid);
  230.         if (Location != NULL)
  231.             continue;
  232.         if (create_names_entry(pw) == NULL)
  233.             return(NULL);
  234.         if (pw->pw_uid == uid)
  235.             return(pw->pw_name);
  236.     }
  237.     init = 2;
  238.     endpwent();
  239.     return(NULL);
  240. }
  241.