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