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 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 4564811019SFrançois Revol LoginApp::~LoginApp() 4664811019SFrançois Revol { 4764811019SFrançois Revol } 4864811019SFrançois Revol 4964811019SFrançois Revol 5064811019SFrançois Revol void 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 { 64*fa19dd44Slooncraz float sizeDelta = (float)be_plain_font->Size()/12.0f; 65*fa19dd44Slooncraz 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 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 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")*/ { 132f86acdc2SAdrien Destugues printf(B_TRANSLATE("Login application for Haiku\nUsage:\n")); 1333813268cSFrançois Revol printf("%s [--nonmodal] [--edit]\n", argv[0]); 134f86acdc2SAdrien Destugues printf(B_TRANSLATE("--nonmodal Do not make the window modal\n")); 135f86acdc2SAdrien Destugues printf(B_TRANSLATE("--edit Launch in shelf editting mode to " 136f86acdc2SAdrien Destugues "allow customizing the desktop.\n")); 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 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 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 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