]> granicus.if.org Git - shadow/blob - libmisc/loginprompt.c
* libmisc/getlong.c: Reset errno before calling strtol().
[shadow] / libmisc / loginprompt.c
1 /*
2  * Copyright (c) 1989 - 1993, Julianne Frances Haugh
3  * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4  * Copyright (c) 2003 - 2005, Tomasz Kłoczko
5  * Copyright (c) 2008       , Nicolas François
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the copyright holders or contributors may not be used to
17  *    endorse or promote products derived from this software without
18  *    specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <config.h>
34
35 #ident "$Id$"
36
37 #include <stdio.h>
38 #include <signal.h>
39 #include <ctype.h>
40 #include "prototypes.h"
41 #include "defines.h"
42 #include "getdef.h"
43
44 static void login_exit (unused int sig)
45 {
46         exit (1);
47 }
48
49 /*
50  * login_prompt - prompt the user for their login name
51  *
52  * login_prompt() displays the standard login prompt.  If ISSUE_FILE
53  * is set in login.defs, this file is displayed before the prompt.
54  */
55
56 void login_prompt (const char *prompt, char *name, int namesize)
57 {
58         char buf[1024];
59
60 #define MAX_ENV 32
61         char *envp[MAX_ENV];
62         int envc;
63         char *cp;
64         int i;
65         FILE *fp;
66
67         RETSIGTYPE (*sigquit) (int);
68 #ifdef  SIGTSTP
69         RETSIGTYPE (*sigtstp) (int);
70 #endif
71
72         /*
73          * There is a small chance that a QUIT character will be part of
74          * some random noise during a prompt.  Deal with this by exiting
75          * instead of core dumping.  If SIGTSTP is defined, do the same
76          * thing for that signal.
77          */
78
79         sigquit = signal (SIGQUIT, login_exit);
80 #ifdef  SIGTSTP
81         sigtstp = signal (SIGTSTP, login_exit);
82 #endif
83
84         /*
85          * See if the user has configured the issue file to
86          * be displayed and display it before the prompt.
87          */
88
89         if (prompt) {
90                 cp = getdef_str ("ISSUE_FILE");
91                 if (NULL != cp) {
92                         fp = fopen (cp, "r");
93                         if (NULL != fp) {
94                                 while ((i = getc (fp)) != EOF) {
95                                         putc (i, stdout);
96                                 }
97
98                                 (void) fclose (fp);
99                         }
100                 }
101                 gethostname (buf, sizeof buf);
102                 printf (prompt, buf);
103                 (void) fflush (stdout);
104         }
105
106         /* 
107          * Read the user's response.  The trailing newline will be
108          * removed.
109          */
110
111         memzero (buf, sizeof buf);
112         if (fgets (buf, (int) sizeof buf, stdin) != buf) {
113                 exit (1);
114         }
115
116         cp = strchr (buf, '\n');
117         if (NULL == cp) {
118                 exit (1);
119         }
120         *cp = '\0';             /* remove \n [ must be there ] */
121
122         /*
123          * Skip leading whitespace.  This makes "  username" work right.
124          * Then copy the rest (up to the end or the first "non-graphic"
125          * character into the username.
126          */
127
128         for (cp = buf; *cp == ' ' || *cp == '\t'; cp++);
129
130         for (i = 0; i < namesize - 1 && isgraph (*cp); name[i++] = *cp++);
131         while (isgraph (*cp)) {
132                 cp++;
133         }
134
135         if ('\0' != *cp) {
136                 cp++;
137         }
138
139         name[i] = '\0';
140
141         /*
142          * This is a disaster, at best.  The user may have entered extra
143          * environmental variables at the prompt.  There are several ways
144          * to do this, and I just take the easy way out.
145          */
146
147         if ('\0' != *cp) {      /* process new variables */
148                 char *nvar;
149                 int count = 1;
150
151                 for (envc = 0; envc < MAX_ENV; envc++) {
152                         nvar = strtok ((0 != envc) ? (char *) 0 : cp, " \t,");
153                         if (NULL == nvar) {
154                                 break;
155                         }
156                         if (strchr (nvar, '=') != NULL) {
157                                 envp[envc] = nvar;
158                         } else {
159                                 envp[envc] = xmalloc (strlen (nvar) + 32);
160                                 sprintf (envp[envc], "L%d=%s", count++, nvar);
161                         }
162                 }
163                 set_env (envc, envp);
164         }
165
166         /*
167          * Set the SIGQUIT handler back to its original value
168          */
169
170         (void) signal (SIGQUIT, sigquit);
171 #ifdef  SIGTSTP
172         (void) signal (SIGTSTP, sigtstp);
173 #endif
174 }
175