Start 1.33.0 development cycle
[oweals/busybox.git] / libbb / login.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * issue.c: issue printing code
4  *
5  * Copyright (C) 2003 Bastian Blank <waldi@tuxbox.org>
6  *
7  * Optimize and correcting OCRNL by Vladimir Oleynik <dzo@simtreas.ru>
8  *
9  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10  */
11 #include "libbb.h"
12 /* After libbb.h, since it needs sys/types.h on some systems */
13 #include <sys/utsname.h>
14
15 #define LOGIN " login: "
16
17 static const char fmtstr_d[] ALIGN1 = "%A, %d %B %Y";
18
19 void FAST_FUNC print_login_issue(const char *issue_file, const char *tty)
20 {
21         FILE *fp;
22         int c;
23         char buf[256+1];
24         const char *outbuf;
25         time_t t;
26         struct utsname uts;
27
28         time(&t);
29         uname(&uts);
30
31         puts("\r");  /* start a new line */
32
33         fp = fopen_for_read(issue_file);
34         if (!fp)
35                 return;
36         while ((c = fgetc(fp)) != EOF) {
37                 outbuf = buf;
38                 buf[0] = c;
39                 buf[1] = '\0';
40                 if (c == '\n') {
41                         buf[1] = '\r';
42                         buf[2] = '\0';
43                 }
44                 if (c == '\\' || c == '%') {
45                         c = fgetc(fp);
46                         switch (c) {
47 //From getty manpage (* - supported by us)
48 //========================================
49 //4 or 4{interface}
50 //  Insert the IPv4 address of the network interface (example: \4{eth0}).
51 //  If the interface argument is not specified, then select the first
52 //  fully configured (UP, non-LOOPBACK, RUNNING) interface.
53 //6 or 6{interface} -- The same as \4 but for IPv6.
54 //b -- Insert the baudrate of the current line.
55 //*d -- Insert the current date.
56 //*t -- Insert the current time.
57 //e or e{name}
58 //  Translate the human-readable name to an escape sequence and insert it
59 //  (for example: \e{red}Alert text.\e{reset}).  If the name argument
60 //  is not specified, then insert \033. The currently supported names are:
61 //  black, blink, blue, bold, brown, cyan, darkgray, gray, green, halfbright,
62 //  lightblue, lightcyan, lightgray, lightgreen, lightmagenta, lightred,
63 //  magenta, red, reset, reverse, and yellow. Unknown names are ignored.
64 //*s
65 //  Insert the system name (the name of the operating system - `uname -s`)
66 //*S or S{VARIABLE}
67 //  Insert the VARIABLE data from /etc/os-release.
68 //  If the VARIABLE argument is not specified, use PRETTY_NAME.
69 //  If PRETTY_NAME is not in /etc/os-release, \S is the same as \s.
70 //*l -- Insert the name of the current tty line.
71 //*m -- Insert the architecture identifier of the machine: `uname -m`.
72 //*n -- Insert the nodename of the machine: `uname -n`.
73 //*o -- Insert the NIS domainname of the machine.  Same as `hostname -d'.
74 //*O -- Insert the DNS domainname of the machine.
75 //*r -- Insert the release number of the OS: `uname -r`.
76 //u -- Insert the number of current users logged in.
77 //U -- Insert the string "1 user" or "N users" (current users logged in).
78 //*v -- Insert the version of the OS, e.g. the build-date etc: `uname -v`.
79 //We also implement:
80 //*D -- same as \O "DNS domainname"
81 //*h -- same as \n "nodename"
82
83                         case 'S':
84                                 /* minimal implementation, not reading /etc/os-release */
85                                 /*FALLTHROUGH*/
86                         case 's':
87                                 outbuf = uts.sysname;
88                                 break;
89                         case 'n':
90                         case 'h':
91                                 outbuf = uts.nodename;
92                                 break;
93                         case 'r':
94                                 outbuf = uts.release;
95                                 break;
96                         case 'v':
97                                 outbuf = uts.version;
98                                 break;
99                         case 'm':
100                                 outbuf = uts.machine;
101                                 break;
102 /* The field domainname of struct utsname is Linux specific. */
103 #if defined(__linux__)
104                         case 'D':
105                         case 'o':
106                         case 'O':
107                                 outbuf = uts.domainname;
108                                 break;
109 #endif
110                         case 'd':
111                                 strftime(buf, sizeof(buf), fmtstr_d, localtime(&t));
112                                 break;
113                         case 't':
114                                 strftime_HHMMSS(buf, sizeof(buf), &t);
115                                 break;
116                         case 'l':
117                                 outbuf = tty;
118                                 break;
119                         default:
120                                 buf[0] = c;
121                         }
122                 }
123                 fputs(outbuf, stdout);
124         }
125         fclose(fp);
126         fflush_all();
127 }
128
129 void FAST_FUNC print_login_prompt(void)
130 {
131         char *hostname = safe_gethostname();
132
133         fputs(hostname, stdout);
134         fputs(LOGIN, stdout);
135         fflush_all();
136         free(hostname);
137 }
138
139 /* Clear dangerous stuff, set PATH */
140 static const char forbid[] ALIGN1 =
141         "ENV" "\0"
142         "BASH_ENV" "\0"
143         "HOME" "\0"
144         "IFS" "\0"
145         "SHELL" "\0"
146         "LD_LIBRARY_PATH" "\0"
147         "LD_PRELOAD" "\0"
148         "LD_TRACE_LOADED_OBJECTS" "\0"
149         "LD_BIND_NOW" "\0"
150         "LD_AOUT_LIBRARY_PATH" "\0"
151         "LD_AOUT_PRELOAD" "\0"
152         "LD_NOWARN" "\0"
153         "LD_KEEPDIR" "\0";
154
155 int FAST_FUNC sanitize_env_if_suid(void)
156 {
157         const char *p;
158
159         if (getuid() == geteuid())
160                 return 0;
161
162         p = forbid;
163         do {
164                 unsetenv(p);
165                 p += strlen(p) + 1;
166         } while (*p);
167         putenv((char*)bb_PATH_root_path);
168
169         return 1; /* we indeed were run by different user! */
170 }