1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2013 Gary Mills
  24  *
  25  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 
  29 /*      Copyright (c) 1988 AT&T     */
  30 /*        All Rights Reserved   */
  31 
  32 #pragma weak _getlogin = getloginx
  33 #pragma weak _getlogin_r = getloginx_r
  34 
  35 #include "lint.h"
  36 #include <sys/types.h>
  37 #include <sys/stat.h>
  38 #include <fcntl.h>
  39 #include <string.h>
  40 #include <stdlib.h>
  41 #include <limits.h>
  42 #include "utmpx.h"
  43 #include <unistd.h>
  44 #include <errno.h>
  45 #include <thread.h>
  46 #include <synch.h>
  47 #include <mtlib.h>
  48 #include "tsd.h"
  49 
  50 /* Revert the renames done in unistd.h */
  51 #ifdef  __PRAGMA_REDEFINE_EXTNAME
  52 #pragma redefine_extname        getlogint       getlogin
  53 #pragma redefine_extname        getlogint_r     getlogin_r
  54 #pragma redefine_extname        __posix_getlogint_r     __posix_getlogin_r
  55 #else   /* __PRAGMA_REDEFINE_EXTNAME */
  56 #ifdef  getlogin
  57 #undef  getlogin
  58 #endif  /* getlogin */
  59 #ifdef  getlogin_r
  60 #undef  getlogin_r
  61 #endif  /* getlogin_r */
  62 #ifdef  __posix_getlogin_r
  63 #undef  __posix_getlogin_r
  64 #endif  /* __posix_getlogin_r */
  65 #define getlogint       getlogin
  66 #define getlogint_r     getlogin_r
  67 #define __posix_getlogint_r     __posix_getlogin_r
  68 #endif  /* __PRAGMA_REDEFINE_EXTNAME */
  69 
  70 /*
  71  * Use the full length of a login name.
  72  * The utmpx interface provides for a 32 character login name.
  73  */
  74 #define NMAX    (sizeof (((struct utmpx *)0)->ut_user))
  75 
  76 /*
  77  * Common function
  78  */
  79 static char *
  80 getl_r_common(char *answer, size_t namelen, size_t maxlen)
  81 {
  82         int             uf;
  83         off64_t         me;
  84         struct futmpx   ubuf;
  85 
  86         if ((me = (off64_t)ttyslot()) < 0)
  87                 return (NULL);
  88         if ((uf = open64(UTMPX_FILE, 0)) < 0)
  89                 return (NULL);
  90         (void) lseek64(uf, me * sizeof (ubuf), SEEK_SET);
  91         if (read(uf, &ubuf, sizeof (ubuf)) != sizeof (ubuf)) {
  92                 (void) close(uf);
  93                 return (NULL);
  94         }
  95         (void) close(uf);
  96         if (ubuf.ut_user[0] == '\0')
  97                 return (NULL);
  98 
  99         /* Insufficient buffer size */
 100         if (namelen < strnlen(&ubuf.ut_user[0], maxlen)) {
 101                 errno = ERANGE;
 102                 return (NULL);
 103         }
 104         (void) strncpy(&answer[0], &ubuf.ut_user[0], maxlen);
 105         answer[maxlen] = '\0';
 106         return (&answer[0]);
 107 }
 108 
 109 /*
 110  * POSIX.1c Draft-6 version of the function getlogin_r.
 111  * It was implemented by Solaris 2.3.
 112  */
 113 char *
 114 getlogint_r(char *answer, int namelen)
 115 {
 116         return (getl_r_common(answer, (size_t)namelen, LOGNAME_MAX_TRAD));
 117 }
 118 
 119 /*
 120  * POSIX.1c standard version of the function getlogin_r.
 121  * User gets it via static getlogin_r from the header file.
 122  */
 123 int
 124 __posix_getlogint_r(char *name, int namelen)
 125 {
 126         int nerrno = 0;
 127         int oerrno = errno;
 128 
 129         errno = 0;
 130         if (getl_r_common(name, (size_t)namelen, LOGNAME_MAX_TRAD) == NULL) {
 131                 if (errno == 0)
 132                         nerrno = EINVAL;
 133                 else
 134                         nerrno = errno;
 135         }
 136         errno = oerrno;
 137         return (nerrno);
 138 }
 139 
 140 char *
 141 getlogint(void)
 142 {
 143         char *answer = tsdalloc(_T_LOGIN, LOGIN_NAME_MAX_TRAD, NULL);
 144 
 145         if (answer == NULL)
 146                 return (NULL);
 147         return (getl_r_common(answer, LOGIN_NAME_MAX_TRAD, LOGNAME_MAX_TRAD));
 148 }
 149 
 150 /*
 151  * POSIX.1c Draft-6 version of the function getlogin_r.
 152  * It was implemented by Solaris 2.3.
 153  * For extended login names, selected by redefine_extname in unistd.h.
 154  */
 155 char *
 156 getloginx_r(char *answer, int namelen)
 157 {
 158         return (getl_r_common(answer, (size_t)namelen, NMAX));
 159 }
 160 
 161 /*
 162  * POSIX.1c standard version of the function getlogin_r.
 163  * User gets it via static getlogin_r from the header file.
 164  * For extended login names, selected by redefine_extname in unistd.h.
 165  */
 166 int
 167 __posix_getloginx_r(char *name, int namelen)
 168 {
 169         int nerrno = 0;
 170         int oerrno = errno;
 171 
 172         errno = 0;
 173         if (getl_r_common(name, (size_t)namelen, NMAX) == NULL) {
 174                 if (errno == 0)
 175                         nerrno = EINVAL;
 176                 else
 177                         nerrno = errno;
 178         }
 179         errno = oerrno;
 180         return (nerrno);
 181 }
 182 
 183 /*
 184  * For extended login names, selected by redefine_extname in unistd.h.
 185  */
 186 char *
 187 getloginx(void)
 188 {
 189         char *answer = tsdalloc(_T_LOGIN, LOGIN_NAME_MAX, NULL);
 190 
 191         if (answer == NULL)
 192                 return (NULL);
 193         return (getl_r_common(answer, LOGIN_NAME_MAX, NMAX));
 194 }