Problems running smbclient noninteractively
Russell Kliese
russell at eminence.com.au
Fri Feb 18 02:59:55 GMT 2005
Michael B Allen wrote:
>Russell Kliese said:
>
>
>>Is there problems running smbpasswd noninteractivly?
>>
>>
>
>A lot of programs behave differently depending on whether or not their
>connected to a terminal. You could try system() but the only sure-fire way
>to run an interactive program without a terminal is to do I/O with a pty
>[1] like an xterm would.
>
>
Thanks for your help. I ended up using expect to interact with
smbpasswd. I have included a test application I wrote because it might
be helpful to others (particularly since the documentation for expect is
quite sparse). I hope this isn't too off topic.
Russell
/*
* Example of using expect with smbpasswd to add a user and set their
password
*
* Perhaps not the most eloquent solution
*
* Compile with gcc -o smbpasswdTest -lexpect5.42 -lstdc++ smbpasswdTest.cpp
*/
#include <stdio.h>
#include <string>
#include <iostream>
#include <sstream>
#include <tcl8.4/expect.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
/** Causes the stdout to be written to /dev/null
* upon instantiation
*/
class StdoutObliviate {
public:
StdoutObliviate() {
int fdNull;
if(-1 == (fdNull = open("/dev/null", O_WRONLY)))
throw std::string("Couldn't open /dev/null");
oldStdOut = dup(fileno(stdout));
dup2(fdNull, fileno(stdout));
}
~StdoutObliviate() {
dup2(oldStdOut, fileno(stdout));
}
private:
int oldStdOut;
};
/** Adds a user and sets their password using smbpasswd
*
* @param userName The user name of the user to add
* @param password The password to assign to the user
* \raises std::string with a description of what caused the exception
*/
void createSMBUser(std::string userName, std::string password) {
/*
* Write everything on stdout to /dev/null
*/
StdoutObliviate stdoutObliviate;
int fd;
exp_timeout = 2; // 2 seconds timeout. It shouldn't take longer than this.
/*
* turn off echo
*/
exp_stty_init = "-echo";
/*
* fire up smbpasswd with the appropriate arguments
*/
if (-1 == (fd = exp_spawnl("/usr/bin/smbpasswd","smbpasswd", "-a",
"-s", "russell", (char *)0))) {
throw std::string(std::string("Couldn't spawn smbpasswd: ") +
strerror(errno));
}
/*
* send the password
*/
std::string input = password + "\r" + password + "\r";
if (-1 == write(fd,input.c_str(),input.length())) {
throw std::string("Error sending password to smbpasswd");
}
/*
* Wait for smbpasswd to finish (or timeout)
*/
switch (exp_expectl(fd,exp_end)) {
case EXP_TIMEOUT:
throw std::string("smbpasswd timed out after sending password");
case EXP_EOF:
std::string expBuffer(exp_buffer);
if(expBuffer.length())
std::cerr << "smbpasswd chatter: " << exp_buffer << std::endl;
}
/*
* See how smbpasswd finished
*/
int status;
wait(&status); // wait for smbpasswd to terminate
if(WIFEXITED(status)) {
int returnValue = WEXITSTATUS(status);
if(returnValue != 0) {
std::ostringstream os;
os << "smbpasswd exited with exit value: " << returnValue;
throw std::string(os.str());
}
} else {
throw std::string("smbpasswd exited abnormally");
}
}
int main(){
try {
createSMBUser("user", "test");
std::cout << "User created successfully" << std::endl;
return 0;
} catch (std::string& exception) {
std::cerr << "Problem adding user: " << exception << std::endl;
}
return 1;
}
--
<http://www.eminence.com.au/> Eminence Technology Pty Ltd
PO Box 118, Moorooka QLD 4105
Web: www.eminence.com.au <http://www.eminence.com.au/>
Ph: +61-7-3277-4100
Fax: +61-7-3277-4577
More information about the samba-technical
mailing list