Back to index

glibc  2.9
tst-utmp.c
Go to the documentation of this file.
00001 /* Tests for UTMP functions.
00002    Copyright (C) 1998, 2001-2003 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <errno.h>
00022 #include <error.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <sys/types.h>
00026 #include <time.h>
00027 
00028 #ifdef UTMPX
00029 # include <utmpx.h>
00030 # define utmp utmpx
00031 # define utmpname utmpxname
00032 # define setutent setutxent
00033 # define getutent getutxent
00034 # define endutent endutxent
00035 # define getutline getutxline
00036 # define getutid getutxid
00037 # define pututline pututxline
00038 #else
00039 # include <utmp.h>
00040 #endif
00041 
00042 
00043 #if _HAVE_UT_TYPE || defined UTMPX
00044 
00045 /* Prototype for our test function.  */
00046 static int do_test (int argc, char *argv[]);
00047 
00048 /* We have a preparation function.  */
00049 static void do_prepare (int argc, char *argv[]);
00050 #define PREPARE do_prepare
00051 
00052 /* This defines the `main' function and some more.  */
00053 #include <test-skeleton.c>
00054 
00055 
00056 /* These are for the temporary file we generate.  */
00057 char *name;
00058 int fd;
00059 
00060 static void
00061 do_prepare (int argc, char *argv[])
00062 {
00063   size_t name_len;
00064 
00065   name_len = strlen (test_dir);
00066   name = malloc (name_len + sizeof ("/utmpXXXXXX"));
00067   mempcpy (mempcpy (name, test_dir, name_len),
00068           "/utmpXXXXXX", sizeof ("/utmpXXXXXX"));
00069   add_temp_file (name);
00070 
00071   /* Open our test file.  */
00072   fd = mkstemp (name);
00073   if (fd == -1)
00074     error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
00075 }
00076 
00077 struct utmp entry[] =
00078 {
00079 #if _HAVE_UT_TV || defined UTMPX
00080 #define UT(a)  .ut_tv = { .tv_sec = (a)}
00081 #else
00082 #define UT(a)  .ut_time = (a)
00083 #endif
00084 
00085   { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) },
00086   { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) },
00087   { .ut_type = INIT_PROCESS, .ut_pid = 5, .ut_id = "si", UT(3000) },
00088   { .ut_type = LOGIN_PROCESS, .ut_pid = 23, .ut_line = "tty1", .ut_id = "1",
00089     .ut_user = "LOGIN", UT(4000) },
00090   { .ut_type = USER_PROCESS, .ut_pid = 24, .ut_line = "tty2", .ut_id = "2",
00091     .ut_user = "albert", UT(8000) },
00092   { .ut_type = USER_PROCESS, .ut_pid = 196, .ut_line = "ttyp0", .ut_id = "p0",
00093     .ut_user = "niels", UT(10000) },
00094   { .ut_type = DEAD_PROCESS, .ut_line = "ttyp1", .ut_id = "p1", UT(16000) },
00095   { .ut_type = EMPTY },
00096   { .ut_type = EMPTY }
00097 };
00098 int num_entries = sizeof entry / sizeof (struct utmp);
00099 
00100 time_t entry_time = 20000;
00101 pid_t entry_pid = 234;
00102 
00103 static int
00104 do_init (void)
00105 {
00106   int n;
00107 
00108   setutent ();
00109 
00110   for (n = 0; n < num_entries; n++)
00111     {
00112       if (pututline (&entry[n]) == NULL)
00113        {
00114          error (0, errno, "cannot write UTMP entry");
00115          return 1;
00116        }
00117     }
00118 
00119   endutent ();
00120 
00121   return 0;
00122 }
00123 
00124 
00125 static int
00126 do_check (void)
00127 {
00128   struct utmp *ut;
00129   int n;
00130 
00131   setutent ();
00132 
00133   n = 0;
00134   while ((ut = getutent ()))
00135     {
00136       if (n < num_entries &&
00137          memcmp (ut, &entry[n], sizeof (struct utmp)))
00138        {
00139          error (0, 0, "UTMP entry does not match");
00140          return 1;
00141        }
00142 
00143       n++;
00144     }
00145 
00146   if (n != num_entries)
00147     {
00148       error (0, 0, "number of UTMP entries is incorrect");
00149       return 1;
00150     }
00151 
00152   endutent ();
00153 
00154   return 0;
00155 }
00156 
00157 static int
00158 simulate_login (const char *line, const char *user)
00159 {
00160   int n;
00161 
00162   for (n = 0; n < num_entries; n++)
00163     {
00164       if (strcmp (line, entry[n].ut_line) == 0 ||
00165          entry[n].ut_type == DEAD_PROCESS)
00166        {
00167          if (entry[n].ut_pid == DEAD_PROCESS)
00168            entry[n].ut_pid = (entry_pid += 27);
00169          entry[n].ut_type = USER_PROCESS;
00170          strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user));
00171 #if _HAVE_UT_TV - 0 || defined UTMPX
00172          entry[n].ut_tv.tv_sec = (entry_time += 1000);
00173 #else
00174           entry[n].ut_time = (entry_time += 1000);
00175 #endif
00176          setutent ();
00177 
00178          if (pututline (&entry[n]) == NULL)
00179            {
00180              error (0, errno, "cannot write UTMP entry");
00181              return 1;
00182            }
00183 
00184          endutent ();
00185 
00186          return 0;
00187        }
00188     }
00189 
00190   error (0, 0, "no entries available");
00191   return 1;
00192 }
00193 
00194 static int
00195 simulate_logout (const char *line)
00196 {
00197   int n;
00198 
00199   for (n = 0; n < num_entries; n++)
00200     {
00201       if (strcmp (line, entry[n].ut_line) == 0)
00202        {
00203          entry[n].ut_type = DEAD_PROCESS;
00204          strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user));
00205 #if _HAVE_UT_TV - 0 || defined UTMPX
00206           entry[n].ut_tv.tv_sec = (entry_time += 1000);
00207 #else
00208           entry[n].ut_time = (entry_time += 1000);
00209 #endif
00210          setutent ();
00211 
00212          if (pututline (&entry[n]) == NULL)
00213            {
00214              error (0, errno, "cannot write UTMP entry");
00215              return 1;
00216            }
00217 
00218          endutent ();
00219 
00220          return 0;
00221        }
00222     }
00223 
00224   error (0, 0, "no entry found for `%s'", line);
00225   return 1;
00226 }
00227 
00228 static int
00229 check_login (const char *line)
00230 {
00231   struct utmp *up;
00232   struct utmp ut;
00233   int n;
00234 
00235   setutent ();
00236 
00237   strcpy (ut.ut_line, line);
00238   up = getutline (&ut);
00239   if (up == NULL)
00240     {
00241       error (0, errno, "cannot get entry for line `%s'", line);
00242       return 1;
00243     }
00244 
00245   endutent ();
00246 
00247   for (n = 0; n < num_entries; n++)
00248     {
00249       if (strcmp (line, entry[n].ut_line) == 0)
00250        {
00251          if (memcmp (up, &entry[n], sizeof (struct utmp)))
00252            {
00253              error (0, 0, "UTMP entry does not match");
00254              return 1;
00255            }
00256 
00257          return 0;
00258        }
00259     }
00260 
00261   error (0, 0, "bogus entry for line `%s'", line);
00262   return 1;
00263 }
00264 
00265 static int
00266 check_logout (const char *line)
00267 {
00268   struct utmp ut;
00269 
00270   setutent ();
00271 
00272   strcpy (ut.ut_line, line);
00273   if (getutline (&ut) != NULL)
00274     {
00275       error (0, 0, "bogus login entry for `%s'", line);
00276       return 1;
00277     }
00278 
00279   endutent ();
00280 
00281   return 0;
00282 }
00283 
00284 static int
00285 check_id (const char *id)
00286 {
00287   struct utmp *up;
00288   struct utmp ut;
00289   int n;
00290 
00291   setutent ();
00292 
00293   ut.ut_type = USER_PROCESS;
00294   strcpy (ut.ut_id, id);
00295   up = getutid (&ut);
00296   if (up == NULL)
00297     {
00298       error (0, errno, "cannot get entry for ID `%s'", id);
00299       return 1;
00300     }
00301 
00302   endutent ();
00303 
00304   for (n = 0; n < num_entries; n++)
00305     {
00306       if (strcmp (id, entry[n].ut_id) == 0)
00307        {
00308          if (memcmp (up, &entry[n], sizeof (struct utmp)))
00309            {
00310              error (0, 0, "UTMP entry does not match");
00311              return 1;
00312            }
00313 
00314          return 0;
00315        }
00316     }
00317 
00318   error (0, 0, "bogus entry for ID `%s'", id);
00319   return 1;
00320 }
00321 
00322 static int
00323 check_type (int type)
00324 {
00325   struct utmp *up;
00326   struct utmp ut;
00327   int n;
00328 
00329   setutent ();
00330 
00331   ut.ut_type = type;
00332   up = getutid (&ut);
00333   if (up == NULL)
00334     {
00335       error (0, errno, "cannot get entry for type `%d'", type);
00336       return 1;
00337     }
00338 
00339   endutent ();
00340 
00341   for (n = 0; n < num_entries; n++)
00342     {
00343       if (type == entry[n].ut_type)
00344        {
00345          if (memcmp (up, &entry[n], sizeof (struct utmp)))
00346            {
00347              error (0, 0, "UTMP entry does not match");
00348              return 1;
00349            }
00350 
00351          return 0;
00352        }
00353     }
00354 
00355   error (0, 0, "bogus entry for type `%d'", type);
00356   return 1;
00357 }
00358 
00359 static int
00360 do_test (int argc, char *argv[])
00361 {
00362   int result = 0;
00363 
00364   utmpname (name);
00365 
00366   result |= do_init ();
00367   result |= do_check ();
00368 
00369   result |= simulate_login ("tty1", "erwin");
00370   result |= do_check ();
00371 
00372   result |= simulate_login ("ttyp1", "paul");
00373   result |= do_check ();
00374 
00375   result |= simulate_logout ("tty2");
00376   result |= do_check ();
00377 
00378   result |= simulate_logout ("ttyp0");
00379   result |= do_check ();
00380 
00381   result |= simulate_login ("ttyp2", "richard");
00382   result |= do_check ();
00383 
00384   result |= check_login ("tty1");
00385   result |= check_logout ("ttyp0");
00386   result |= check_id ("p1");
00387   result |= check_id ("2");
00388   result |= check_id ("si");
00389   result |= check_type (BOOT_TIME);
00390   result |= check_type (RUN_LVL);
00391 
00392   return result;
00393 }
00394 
00395 #else
00396 
00397 /* No field 'ut_type' in struct utmp.  */
00398 int
00399 main ()
00400 {
00401   return 0;
00402 }
00403 
00404 #endif