/*
* Change message system password. Run as:
* msgpass [ -e ] server [ port ] account
* It will request old and new passwords, and attempt to change it
* on the server.
*/
#include <iostream>
#include <sstream>
#include <string>
#include <cctype>
#include <cstdlib>
#include <cleansocks.h>
#include <cleanip.h>
#include <cleanbuf.h>
#include "getpass.h"
using namespace cleansocks;
/* Program name. */
std::string pname;
/* Echo flag. If true, the program displays its conversation. */
bool echo = false;
/* Print a message and exit. */
void wham(std::string msg)
{
/* See what message we have here. */
std::cerr << pname << ": " << msg << std::endl;
exit(1);
}
/* Get a line from the server. Return code, negative for errors. If not
the expected code, we will exit with a message. */
int getcode(buffered_socket &c, int expected)
{
// Get a line. Add a plain C string terminator to make a valid
// plain C string with the \r\n removed.
char buf[1024];
int n = recvln(c, buf, sizeof buf);
buf[n - 2] = 0;
// Echo the server response.
if(echo) std::cout << "<< " << buf << std::endl;
// Collect the info from the line. Use a C++ string stream to read
// the line as though it were input.
std::istringstream iss(buf);
std::string resp; iss >> resp;
int code; iss >> code >> std::ws;
std::string emsg; getline(iss, emsg, '\r');
if(resp == "E") code = -code;
// See if we got what was expected.
if(code != expected)
{
close(c);
if(code < 0)
wham("Error: " + emsg);
else
wham("Unexpeced response: " + emsg);
}
return code;
}
/* Send a string the server, obeying the global echo flag and adding the \r\n */
void esend(buffered_socket &sock, std::string tosend) {
if(echo) std::cout << ">> " << tosend << std::endl;
send(sock, tosend + "\r\n");
}
int main(int argc, char **argv)
{
// Program name.
pname = argv[0];
// Set the global echo flag.
echo = false;
if(argc >= 2 && std::string(argv[1]) == "-e") {
echo = true;
--argc; ++argv; // Make it go away.
}
// Args!
if(argc < 3 || argc > 4) wham("[ -e ] host [ port ] account");
// Convert the computer name.
IPaddress comp = lookup_host(argv[1]);
// Get the port number and the account name.
IPport port = 45301;
std::string account;
if(isdigit(argv[2][0])) {
port = atoi(argv[2]);
account = argv[3];
} else
account = argv[2];
TCPsocket tc;
try {
// Connect to the server and get the welcome msg.
connect(tc, IPendpoint(comp, port));
buffered_socket conn(tc);
getcode(conn, 100);
// Try to log in.
std::string pwd = getpass("Current password: ");
esend(conn, "IAM " + account + " " + pwd);
getcode(conn, 105);
// Get new password from user.
std::string p1 = getpass("New password: ");
std::string p2 = getpass("Retype: ");
if(p1 != p2)
wham("Passwords don't match");
// Try to set it on the server.
esend(conn, "CHP " + p1);
getcode(conn, 106);
// Wind up.
esend(conn, "BYE");
getcode(conn, 107);
close(conn);
printf("Password changed.\n");
} catch(std::exception &e) {
close(tc);
wham(std::string("Exception: ") + e.what());
}
}