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