xref: /haiku/src/apps/login/LoginApp.cpp (revision 25a7b01d15612846f332751841da3579db313082)
1 /*
2  * Copyright 2008, François Revol, <revol@free.fr>. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <Alert.h>
8 #include <Catalog.h>
9 #include <Screen.h>
10 #include <String.h>
11 #include <View.h>
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <pwd.h>
18 
19 #include "LoginApp.h"
20 #include "LoginWindow.h"
21 #include "DesktopWindow.h"
22 
23 #ifdef __HAIKU__
24 #include <RosterPrivate.h>
25 #include <shadow.h>
26 #include "multiuser_utils.h"
27 #endif
28 
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "Login App"
31 
32 const char *kLoginAppSig = "application/x-vnd.Haiku-Login";
33 
34 
35 LoginApp::LoginApp()
36 	: BApplication(kLoginAppSig),
37 	  fEditShelfMode(false),
38 	  fModalMode(true)
39 {
40 }
41 
42 
43 LoginApp::~LoginApp()
44 {
45 }
46 
47 
48 void
49 LoginApp::ReadyToRun()
50 {
51 	BScreen screen;
52 
53 	if (fEditShelfMode) {
54 		BAlert* alert = new BAlert(B_TRANSLATE("Info"), B_TRANSLATE("You can customize the "
55 			"desktop shown behind the Login application by dropping replicants"
56 			" onto it.\n"
57 			"\n"
58 			"When you are finished just quit the application (Alt-Q)."),
59 			B_TRANSLATE("OK"));
60 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
61 		alert->Go(NULL);
62 	} else {
63 		BRect frame(0, 0, 450, 150);
64 		frame.OffsetBySelf(screen.Frame().Width()/2 - frame.Width()/2,
65 			screen.Frame().Height()/2 - frame.Height()/2);
66 		fLoginWindow = new LoginWindow(frame);
67 		fLoginWindow->Show();
68 	}
69 
70 	fDesktopWindow = new DesktopWindow(screen.Frame(), fEditShelfMode);
71 	fDesktopWindow->Show();
72 	// TODO: add a shelf with Activity Monitor replicant :)
73 }
74 
75 
76 void
77 LoginApp::MessageReceived(BMessage *message)
78 {
79 	bool reboot = false;
80 
81 	switch (message->what) {
82 		case kAttemptLogin:
83 			message->PrintToStream();
84 			TryLogin(message);
85 			// TODO
86 			break;
87 #ifdef __HAIKU__
88 		case kHaltAction:
89 			reboot = false;
90 			// FALLTHROUGH
91 		case kRebootAction:
92 		{
93 			BRoster roster;
94 			BRoster::Private rosterPrivate(roster);
95 			status_t error = rosterPrivate.ShutDown(reboot, false, false);
96 			if (error < B_OK) {
97 				BString msg(B_TRANSLATE("Error: %1"));
98 				msg.ReplaceFirst("%1", strerror(error));
99 				BAlert* alert = new BAlert(("Error"), msg.String(),
100 					B_TRANSLATE("OK"));
101 				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
102 				alert->Go();
103 			}
104 			break;
105 		}
106 		case kSuspendAction:
107 		{
108 			BAlert* alert = new BAlert(B_TRANSLATE("Error"),
109 				B_TRANSLATE("Unimplemented"), B_TRANSLATE("OK"));
110 			alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
111 			alert->Go();
112 			break;
113 		}
114 #endif
115 	default:
116 		BApplication::MessageReceived(message);
117 	}
118 }
119 
120 
121 void
122 LoginApp::ArgvReceived(int32 argc, char **argv)
123 {
124 	for (int i = 1; i < argc; i++) {
125 		BString arg(argv[i]);
126 		//printf("[%d]: %s\n", i, argv[i]);
127 		if (arg == "--edit")
128 			fEditShelfMode = true;
129 		else if (arg == "--nonmodal")
130 			fModalMode = false;
131 		else /*if (arg == "--help")*/ {
132 			printf(B_TRANSLATE("Login application for Haiku\nUsage:\n"));
133 			printf("%s [--nonmodal] [--edit]\n", argv[0]);
134 			printf(B_TRANSLATE("--nonmodal	Do not make the window modal\n"));
135 			printf(B_TRANSLATE("--edit	Launch in shelf editting mode to "
136 				"allow customizing the desktop.\n"));
137 			// just return to the shell
138 			exit((arg == "--help") ? 0 : 1);
139 			return;
140 		}
141 	}
142 }
143 
144 
145 void
146 LoginApp::TryLogin(BMessage *message)
147 {
148 	status_t err;
149 	const char *login;
150 	const char *password;
151 	BMessage reply(kLoginBad);
152 	if (message->FindString("login", &login) == B_OK) {
153 		if (message->FindString("password", &password) < B_OK)
154 			password = NULL;
155 		err = ValidateLogin(login, password);
156 		printf(B_TRANSLATE_COMMENT("ValidateLogin: %s\n",
157 			"A message returned from the ValidateLogin function. "
158 			"It can be \"B_OK\"."), strerror(err));
159 		if (err == B_OK) {
160 			reply.what = kLoginOk;
161 			message->SendReply(&reply);
162 
163 			if (password == NULL)
164 				return;
165 
166 			// start a session
167 			//kSetProgress
168 			StartUserSession(login);
169 		} else {
170 			reply.AddInt32("error", err);
171 			message->SendReply(&reply);
172 			return;
173 		}
174 
175 	} else {
176 		reply.AddInt32("error", EINVAL);
177 		message->SendReply(&reply);
178 		return;
179 	}
180 }
181 
182 
183 status_t
184 LoginApp::ValidateLogin(const char *login, const char *password)
185 {
186 	struct passwd *pwd;
187 
188 	pwd = getpwnam(login);
189 	if (!pwd)
190 		return ENOENT;
191 	if (strcmp(pwd->pw_name, login))
192 		return ENOENT;
193 
194 	if (password == NULL) {
195 		// we only want to check is login exists.
196 		return B_OK;
197 	}
198 
199 #ifdef __HAIKU__
200 	if (verify_password(pwd, getspnam(login), password))
201 		return B_OK;
202 #else
203 	// for testing
204 	if (strcmp(crypt(password, pwd->pw_passwd), pwd->pw_passwd) == 0)
205 		return B_OK;
206 #endif
207 
208 	return B_PERMISSION_DENIED;
209 }
210 
211 
212 status_t
213 LoginApp::StartUserSession(const char *login)
214 {
215 	return B_ERROR;
216 }
217 
218 
219 int
220 LoginApp::getpty(char *pty, char *tty)
221 {
222 	static const char major[] = "pqrs";
223 	static const char minor[] = "0123456789abcdef";
224 	uint32 i, j;
225 	int32 fd = -1;
226 
227 	for (i = 0; i < sizeof(major); i++)
228 	{
229 		for (j = 0; j < sizeof(minor); j++)
230 		{
231 			sprintf(pty, "/dev/pt/%c%c", major[i], minor[j]);
232 			sprintf(tty, "/dev/tt/%c%c", major[i], minor[j]);
233 			fd = open(pty, O_RDWR|O_NOCTTY);
234 			if (fd >= 0)
235 			{
236 				return fd;
237 			}
238 		}
239 	}
240 
241 	return fd;
242 }
243