xref: /haiku/src/apps/login/LoginApp.cpp (revision 4125af2aebf2b054d7acaa98443e5cea3eaaf9b0)
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 <LaunchRoster.h>
20 #include <RosterPrivate.h>
21 #include <shadow.h>
22 
23 #include "multiuser_utils.h"
24 
25 #include "LoginApp.h"
26 #include "LoginWindow.h"
27 #include "DesktopWindow.h"
28 
29 
30 #undef B_TRANSLATION_CONTEXT
31 #define B_TRANSLATION_CONTEXT "Login App"
32 
33 const char *kLoginAppSig = "application/x-vnd.Haiku-Login";
34 
35 
36 LoginApp::LoginApp()
37 	:
38 	BApplication(kLoginAppSig),
39 	fEditShelfMode(false),
40 	fModalMode(true)
41 {
42 }
43 
44 
45 LoginApp::~LoginApp()
46 {
47 }
48 
49 
50 void
51 LoginApp::ReadyToRun()
52 {
53 	BScreen screen;
54 
55 	if (fEditShelfMode) {
56 		BAlert* alert = new BAlert(B_TRANSLATE("Info"), B_TRANSLATE("You can "
57 			"customize the desktop shown behind the Login application by "
58 			"dropping replicants onto it.\n\n"
59 			"When you are finished just quit the application (Cmd-Q)."),
60 			B_TRANSLATE("OK"));
61 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
62 		alert->Go(NULL);
63 	} else {
64 		float sizeDelta = (float)be_plain_font->Size()/12.0f;
65 		BRect frame(0, 0, 450 * sizeDelta, 150 * sizeDelta);
66 		frame.OffsetBySelf(screen.Frame().Width()/2 - frame.Width()/2,
67 			screen.Frame().Height()/2 - frame.Height()/2);
68 		fLoginWindow = new LoginWindow(frame);
69 		fLoginWindow->Show();
70 	}
71 
72 	fDesktopWindow = new DesktopWindow(screen.Frame(), fEditShelfMode);
73 	fDesktopWindow->Show();
74 	// TODO: add a shelf with Activity Monitor replicant :)
75 }
76 
77 
78 void
79 LoginApp::MessageReceived(BMessage *message)
80 {
81 	bool reboot = false;
82 
83 	switch (message->what) {
84 		case kAttemptLogin:
85 			TryLogin(message);
86 			// TODO
87 			break;
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 
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 			puts(B_TRANSLATE("Login application for Haiku\nUsage:"));
133 			printf("%s [--nonmodal] [--edit]\n", argv[0]);
134 			puts(B_TRANSLATE("--nonmodal	Do not make the window modal"));
135 			puts(B_TRANSLATE("--edit	Launch in shelf editing mode to "
136 				"allow customizing the desktop."));
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 	BMessage reply(kLoginBad);
149 	status_t status = B_BAD_VALUE;
150 
151 	const char* login;
152 	if (message->FindString("login", &login) == B_OK) {
153 		const char* password = message->GetString("password");
154 
155 		status = ValidateLogin(login, password);
156 		if (status == B_OK) {
157 			status = BLaunchRoster().StartSession(login);
158 			if (status == B_OK)
159 				Quit();
160 		}
161 
162 		fprintf(stderr, "ValidateLogin: %s\n", strerror(status));
163 	}
164 
165 	if (status == B_OK) {
166 		reply.what = kLoginOk;
167 		message->SendReply(&reply);
168 	} else {
169 		reply.AddInt32("error", status);
170 		message->SendReply(&reply);
171 	}
172 }
173 
174 
175 status_t
176 LoginApp::ValidateLogin(const char *login, const char *password)
177 {
178 	struct passwd *pwd;
179 
180 	pwd = getpwnam(login);
181 	if (pwd == NULL)
182 		return ENOENT;
183 	if (strcmp(pwd->pw_name, login) != 0)
184 		return ENOENT;
185 
186 	if (verify_password(pwd, getspnam(login), password))
187 		return B_OK;
188 
189 	return B_PERMISSION_DENIED;
190 }
191 
192 
193 int
194 LoginApp::getpty(char *pty, char *tty)
195 {
196 	static const char major[] = "pqrs";
197 	static const char minor[] = "0123456789abcdef";
198 	uint32 i, j;
199 	int32 fd = -1;
200 
201 	for (i = 0; i < sizeof(major); i++)
202 	{
203 		for (j = 0; j < sizeof(minor); j++)
204 		{
205 			sprintf(pty, "/dev/pt/%c%c", major[i], minor[j]);
206 			sprintf(tty, "/dev/tt/%c%c", major[i], minor[j]);
207 			fd = open(pty, O_RDWR|O_NOCTTY);
208 			if (fd >= 0)
209 			{
210 				return fd;
211 			}
212 		}
213 	}
214 
215 	return fd;
216 }
217