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 = getlogin
  33 #pragma weak _getlogin_r = getlogin_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 /*
  51  * Use the full length of a login name, from LOGIN_NAME_MAX .
  52  * The utmpx interface provides for a 32 character login name.
  53  */
  54 
  55 /*
  56  * POSIX.1c Draft-6 version of the function getlogin_r.
  57  * It was implemented by Solaris 2.3.
  58  */
  59 char *
  60 getlogin_r(char *answer, int namelen)
  61 {
  62         int             uf;
  63         off64_t         me;
  64         struct futmpx   ubuf;
  65 
  66         /* Required minimum */
  67         if (namelen < _POSIX_LOGIN_NAME_MAX) {
  68                 errno = ERANGE;
  69                 return (NULL);
  70         }
  71 
  72         if ((me = (off64_t)ttyslot()) < 0)
  73                 return (NULL);
  74         if ((uf = open64(UTMPX_FILE, 0)) < 0)
  75                 return (NULL);
  76         (void) lseek64(uf, me * sizeof (ubuf), SEEK_SET);
  77         if (read(uf, &ubuf, sizeof (ubuf)) != sizeof (ubuf)) {
  78                 (void) close(uf);
  79                 return (NULL);
  80         }
  81         (void) close(uf);
  82         if (ubuf.ut_user[0] == '\0')
  83                 return (NULL);
  84 
  85         /* Insufficient buffer size */
  86         if (namelen < strnlen(&ubuf.ut_user[0], LOGIN_NAME_MAX - 1)) {
  87                 errno = ERANGE;
  88                 return (NULL);
  89         }
  90         (void) strncpy(&answer[0], &ubuf.ut_user[0],
  91             LOGIN_NAME_MAX - 1);
  92         answer[LOGIN_NAME_MAX - 1] = '\0';
  93         return (&answer[0]);
  94 }
  95 
  96 /*
  97  * POSIX.1c standard version of the function getlogin_r.
  98  * User gets it via static getlogin_r from the header file.
  99  */
 100 int
 101 __posix_getlogin_r(char *name, int namelen)
 102 {
 103         int nerrno = 0;
 104         int oerrno = errno;
 105 
 106         errno = 0;
 107         if (getlogin_r(name, namelen) == NULL) {
 108                 if (errno == 0)
 109                         nerrno = EINVAL;
 110                 else
 111                         nerrno = errno;
 112         }
 113         errno = oerrno;
 114         return (nerrno);
 115 }
 116 
 117 char *
 118 getlogin(void)
 119 {
 120         char *answer = tsdalloc(_T_LOGIN, LOGIN_NAME_MAX, NULL);
 121 
 122         if (answer == NULL)
 123                 return (NULL);
 124         return (getlogin_r(answer, LOGIN_NAME_MAX));
 125 }