xref: /haiku/src/apps/login/LoginApp.cpp (revision 2710b4f5d4251c5cf88c82b0114ea99b0ef46d22)
134c28c69SFrançois Revol /*
234c28c69SFrançois Revol  * Copyright 2008, François Revol, <revol@free.fr>. All rights reserved.
334c28c69SFrançois Revol  * Distributed under the terms of the MIT License.
434c28c69SFrançois Revol  */
534c28c69SFrançois Revol 
634c28c69SFrançois Revol 
7d5cec752SFrançois Revol #include <Alert.h>
8f86acdc2SAdrien Destugues #include <Catalog.h>
964811019SFrançois Revol #include <Screen.h>
10d5cec752SFrançois Revol #include <String.h>
11e5f2d374SFrançois Revol #include <View.h>
1264811019SFrançois Revol 
1364811019SFrançois Revol #include <stdio.h>
146e1b92abSFrançois Revol #include <stdlib.h>
15d5cec752SFrançois Revol #include <string.h>
1664811019SFrançois Revol #include <unistd.h>
1764811019SFrançois Revol #include <pwd.h>
1864811019SFrançois Revol 
19ac0a462fSAxel Dörfler #include <LaunchRoster.h>
20ac0a462fSAxel Dörfler #include <RosterPrivate.h>
21ac0a462fSAxel Dörfler #include <shadow.h>
22ac0a462fSAxel Dörfler 
23ac0a462fSAxel Dörfler #include "multiuser_utils.h"
24ac0a462fSAxel Dörfler 
2564811019SFrançois Revol #include "LoginApp.h"
2664811019SFrançois Revol #include "LoginWindow.h"
270efb2585SFrançois Revol #include "DesktopWindow.h"
2864811019SFrançois Revol 
29ac018c2fSIngo Weinhold 
30546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
31546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Login App"
32ac018c2fSIngo Weinhold 
3364811019SFrançois Revol const char *kLoginAppSig = "application/x-vnd.Haiku-Login";
3464811019SFrançois Revol 
3564811019SFrançois Revol 
LoginApp()3664811019SFrançois Revol LoginApp::LoginApp()
372824c5d3SAdrien Destugues 	:
382824c5d3SAdrien Destugues 	BApplication(kLoginAppSig),
393813268cSFrançois Revol 	fEditShelfMode(false),
403813268cSFrançois Revol 	fModalMode(true)
4164811019SFrançois Revol {
4264811019SFrançois Revol }
4364811019SFrançois Revol 
4464811019SFrançois Revol 
~LoginApp()4564811019SFrançois Revol LoginApp::~LoginApp()
4664811019SFrançois Revol {
4764811019SFrançois Revol }
4864811019SFrançois Revol 
4964811019SFrançois Revol 
5064811019SFrançois Revol void
ReadyToRun()5164811019SFrançois Revol LoginApp::ReadyToRun()
5264811019SFrançois Revol {
530efb2585SFrançois Revol 	BScreen screen;
540efb2585SFrançois Revol 
550efb2585SFrançois Revol 	if (fEditShelfMode) {
562824c5d3SAdrien Destugues 		BAlert* alert = new BAlert(B_TRANSLATE("Info"), B_TRANSLATE("You can "
572824c5d3SAdrien Destugues 			"customize the desktop shown behind the Login application by "
582824c5d3SAdrien Destugues 			"dropping replicants onto it.\n\n"
592824c5d3SAdrien Destugues 			"When you are finished just quit the application (Cmd-Q)."),
60aed35104SHumdinger 			B_TRANSLATE("OK"));
61aed35104SHumdinger 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
62aed35104SHumdinger 		alert->Go(NULL);
630efb2585SFrançois Revol 	} else {
64fa19dd44Slooncraz 		float sizeDelta = (float)be_plain_font->Size()/12.0f;
65fa19dd44Slooncraz 		BRect frame(0, 0, 450 * sizeDelta, 150 * sizeDelta);
660efb2585SFrançois Revol 		frame.OffsetBySelf(screen.Frame().Width()/2 - frame.Width()/2,
670efb2585SFrançois Revol 			screen.Frame().Height()/2 - frame.Height()/2);
68e5f2d374SFrançois Revol 		fLoginWindow = new LoginWindow(frame);
69e5f2d374SFrançois Revol 		fLoginWindow->Show();
700efb2585SFrançois Revol 	}
71e5f2d374SFrançois Revol 
720efb2585SFrançois Revol 	fDesktopWindow = new DesktopWindow(screen.Frame(), fEditShelfMode);
73e5f2d374SFrançois Revol 	fDesktopWindow->Show();
74e5f2d374SFrançois Revol 	// TODO: add a shelf with Activity Monitor replicant :)
7564811019SFrançois Revol }
7664811019SFrançois Revol 
7764811019SFrançois Revol 
7864811019SFrançois Revol void
MessageReceived(BMessage * message)7964811019SFrançois Revol LoginApp::MessageReceived(BMessage *message)
8064811019SFrançois Revol {
81d5cec752SFrançois Revol 	bool reboot = false;
82d5cec752SFrançois Revol 
8364811019SFrançois Revol 	switch (message->what) {
84d65e1397SFrançois Revol 		case kAttemptLogin:
85d5cec752SFrançois Revol 			TryLogin(message);
86d5cec752SFrançois Revol 			// TODO
8764811019SFrançois Revol 			break;
88d5cec752SFrançois Revol 		case kHaltAction:
89d5cec752SFrançois Revol 			reboot = false;
90d5cec752SFrançois Revol 			// FALLTHROUGH
91d5cec752SFrançois Revol 		case kRebootAction:
92d5cec752SFrançois Revol 		{
93d5cec752SFrançois Revol 			BRoster roster;
94d5cec752SFrançois Revol 			BRoster::Private rosterPrivate(roster);
95d5cec752SFrançois Revol 			status_t error = rosterPrivate.ShutDown(reboot, false, false);
96d5cec752SFrançois Revol 			if (error < B_OK) {
97f86acdc2SAdrien Destugues 				BString msg(B_TRANSLATE("Error: %1"));
98f86acdc2SAdrien Destugues 				msg.ReplaceFirst("%1", strerror(error));
99aed35104SHumdinger 				BAlert* alert = new BAlert(("Error"), msg.String(),
100aed35104SHumdinger 					B_TRANSLATE("OK"));
101aed35104SHumdinger 				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
102aed35104SHumdinger 				alert->Go();
103d5cec752SFrançois Revol 			}
104d5cec752SFrançois Revol 			break;
105d5cec752SFrançois Revol 		}
106d5cec752SFrançois Revol 		case kSuspendAction:
107aed35104SHumdinger 		{
108aed35104SHumdinger 			BAlert* alert = new BAlert(B_TRANSLATE("Error"),
109aed35104SHumdinger 				B_TRANSLATE("Unimplemented"), B_TRANSLATE("OK"));
110aed35104SHumdinger 			alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
111aed35104SHumdinger 			alert->Go();
112d5cec752SFrançois Revol 			break;
113aed35104SHumdinger 		}
114ac0a462fSAxel Dörfler 
11564811019SFrançois Revol 		default:
11664811019SFrançois Revol 			BApplication::MessageReceived(message);
11764811019SFrançois Revol 	}
11864811019SFrançois Revol }
11964811019SFrançois Revol 
12064811019SFrançois Revol 
12164811019SFrançois Revol void
ArgvReceived(int32 argc,char ** argv)1220efb2585SFrançois Revol LoginApp::ArgvReceived(int32 argc, char **argv)
1230efb2585SFrançois Revol {
1247974d3dcSStephan Aßmus 	for (int i = 1; i < argc; i++) {
1253813268cSFrançois Revol 		BString arg(argv[i]);
1263813268cSFrançois Revol 		//printf("[%d]: %s\n", i, argv[i]);
1273813268cSFrançois Revol 		if (arg == "--edit")
1280efb2585SFrançois Revol 			fEditShelfMode = true;
1293813268cSFrançois Revol 		else if (arg == "--nonmodal")
1303813268cSFrançois Revol 			fModalMode = false;
1313813268cSFrançois Revol 		else /*if (arg == "--help")*/ {
132198e5ee2SColdfirex 			puts(B_TRANSLATE("Login application for Haiku\nUsage:"));
1333813268cSFrançois Revol 			printf("%s [--nonmodal] [--edit]\n", argv[0]);
134198e5ee2SColdfirex 			puts(B_TRANSLATE("--nonmodal	Do not make the window modal"));
135*4125af2aSNiels Sascha Reedijk 			puts(B_TRANSLATE("--edit	Launch in shelf editing mode to "
136198e5ee2SColdfirex 				"allow customizing the desktop."));
1373813268cSFrançois Revol 			// just return to the shell
1383813268cSFrançois Revol 			exit((arg == "--help") ? 0 : 1);
1393813268cSFrançois Revol 			return;
1403813268cSFrançois Revol 		}
1410efb2585SFrançois Revol 	}
1420efb2585SFrançois Revol }
1430efb2585SFrançois Revol 
1440efb2585SFrançois Revol 
1450efb2585SFrançois Revol void
TryLogin(BMessage * message)14664811019SFrançois Revol LoginApp::TryLogin(BMessage *message)
14764811019SFrançois Revol {
148560119c9SAxel Dörfler 	BMessage reply(kLoginBad);
149ac0a462fSAxel Dörfler 	status_t status = B_BAD_VALUE;
150ac0a462fSAxel Dörfler 
15164811019SFrançois Revol 	const char* login;
15264811019SFrançois Revol 	if (message->FindString("login", &login) == B_OK) {
153560119c9SAxel Dörfler 		const char* password = message->GetString("password");
15464811019SFrançois Revol 
155560119c9SAxel Dörfler 		status = ValidateLogin(login, password);
156560119c9SAxel Dörfler 		if (status == B_OK) {
157560119c9SAxel Dörfler 			status = BLaunchRoster().StartSession(login);
158ac0a462fSAxel Dörfler 			if (status == B_OK)
159ac0a462fSAxel Dörfler 				Quit();
160560119c9SAxel Dörfler 		}
16164811019SFrançois Revol 
162ac0a462fSAxel Dörfler 		fprintf(stderr, "ValidateLogin: %s\n", strerror(status));
16364811019SFrançois Revol 	}
16464811019SFrançois Revol 
165ac0a462fSAxel Dörfler 	if (status == B_OK) {
166ac0a462fSAxel Dörfler 		reply.what = kLoginOk;
167220adf9aSFrançois Revol 		message->SendReply(&reply);
168ac0a462fSAxel Dörfler 	} else {
169ac0a462fSAxel Dörfler 		reply.AddInt32("error", status);
170ac0a462fSAxel Dörfler 		message->SendReply(&reply);
17164811019SFrançois Revol 	}
17264811019SFrançois Revol }
17364811019SFrançois Revol 
17464811019SFrançois Revol 
17564811019SFrançois Revol status_t
ValidateLogin(const char * login,const char * password)1760efb2585SFrançois Revol LoginApp::ValidateLogin(const char *login, const char *password)
17764811019SFrançois Revol {
17864811019SFrançois Revol 	struct passwd *pwd;
17964811019SFrançois Revol 
18064811019SFrançois Revol 	pwd = getpwnam(login);
181560119c9SAxel Dörfler 	if (pwd == NULL)
18264811019SFrançois Revol 		return ENOENT;
183560119c9SAxel Dörfler 	if (strcmp(pwd->pw_name, login) != 0)
18464811019SFrançois Revol 		return ENOENT;
18564811019SFrançois Revol 
186ac018c2fSIngo Weinhold 	if (verify_password(pwd, getspnam(login), password))
18764811019SFrançois Revol 		return B_OK;
188d65e1397SFrançois Revol 
189d5cec752SFrançois Revol 	return B_PERMISSION_DENIED;
19064811019SFrançois Revol }
19164811019SFrançois Revol 
19264811019SFrançois Revol 
19364811019SFrançois Revol int
getpty(char * pty,char * tty)19464811019SFrançois Revol LoginApp::getpty(char *pty, char *tty)
19564811019SFrançois Revol {
19664811019SFrançois Revol 	static const char major[] = "pqrs";
19764811019SFrançois Revol 	static const char minor[] = "0123456789abcdef";
19864811019SFrançois Revol 	uint32 i, j;
19964811019SFrançois Revol 	int32 fd = -1;
20064811019SFrançois Revol 
20164811019SFrançois Revol 	for (i = 0; i < sizeof(major); i++)
20264811019SFrançois Revol 	{
20364811019SFrançois Revol 		for (j = 0; j < sizeof(minor); j++)
20464811019SFrançois Revol 		{
20564811019SFrançois Revol 			sprintf(pty, "/dev/pt/%c%c", major[i], minor[j]);
20664811019SFrançois Revol 			sprintf(tty, "/dev/tt/%c%c", major[i], minor[j]);
20764811019SFrançois Revol 			fd = open(pty, O_RDWR|O_NOCTTY);
20864811019SFrançois Revol 			if (fd >= 0)
20964811019SFrançois Revol 			{
21064811019SFrançois Revol 				return fd;
21164811019SFrançois Revol 			}
21264811019SFrançois Revol 		}
21364811019SFrançois Revol 	}
21464811019SFrançois Revol 
21564811019SFrançois Revol 	return fd;
21664811019SFrançois Revol }
217