libexplain  1.4.D001
libexplain/unsetenv_on_error.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2010-2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License as published by
00007  * the Free Software Foundation; either version 3 of the License, or (at
00008  * your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <libexplain/ac/errno.h>
00020 #include <libexplain/ac/stdlib.h>
00021 #include <libexplain/ac/string.h>
00022 
00023 #include <libexplain/unsetenv.h>
00024 #include <libexplain/output.h>
00025 
00026 
00027 #ifndef HAVE_UNSETENV
00028 
00029 extern char     **environ;
00030 
00031 /*
00032  * Maybe we could use putenv instead?
00033  *
00034  * The glibc implementation of putenv has enhanced semantics, in
00035  * that if there is no '=' in the argument to putenv, it does the
00036  * equivalent of unsetenv.  Of course, if we have glibc, then we already
00037  * have unsetenv.  The BSD implementations (and the Solarises, and
00038  * MacOSX) are not documentent to have the behaviour.  Thus, we ignore
00039  * HAVE_PUTENV because it probably can't help us here.
00040  */
00041 
00042 static int
00043 unsetenv(const char *name)
00044 {
00045     char            **ep;
00046     size_t          name_size;
00047 
00048     if (!name || !*name || strchr(name, '='))
00049     {
00050         errno = EINVAL;
00051         return -1;
00052     }
00053     ep = environ;
00054     if (!ep)
00055         return 0;
00056     name_size = strlen(name);
00057     while (*ep)
00058     {
00059         if (!strncmp(*ep, name, name_size) && (*ep)[name_size] == '=')
00060         {
00061             char            **ep2;
00062 
00063             ep2 = ep;
00064             for (;;)
00065             {
00066                 ep2[0] = ep2[1];
00067                 if (!ep2[0])
00068                     break;
00069                 ++ep2;
00070             }
00071             /* keep going, there could be more */
00072         }
00073         else
00074         {
00075             ++ep;
00076         }
00077     }
00078     return 0;
00079 }
00080 
00081 #endif
00082 
00083 int
00084 explain_unsetenv_on_error(const char *name)
00085 {
00086     int             result;
00087 
00088     result = unsetenv(name);
00089     if (result < 0)
00090     {
00091         int             hold_errno;
00092 
00093         hold_errno = errno;
00094         explain_output_error("%s", explain_errno_unsetenv(hold_errno, name));
00095         errno = hold_errno;
00096     }
00097     return result;
00098 }
00099 
00100 
00101 /* vim: set ts=8 sw=4 et : */