Thanks!
See the recent comp.unix.shell thread "Change password in a script."
Moshe
--
jehsom@ angband.org bellsouth.net burdell.org cc.gatech.edu polter.net
nullity.dhs.org resnet.gatech.edu wreck.org yo.dhs.org usa.net; moshe@
medmanager.com; gte741e mj116 @prism.gatech.edu; jacobsonconsulting@
usa.net; moshe@ medmanager.com; ICQ 1900670; Post tech Qs to the NG pls
Speaing only for myself,
Joe Durusau
"Terry E. Rataiczak, Sr." wrote:
>
> I want to write a /bin/sh script that takes and argument and completes the
> passwd username command. Does anyone know how to go about this? I have the
> script taking the arguments and calling passwd, but it just waits for me to
> enter a password. Thanks in Advance.
>
> Thanks!
-- Matt Lesko
matt.advancedatatools@com
[ if you can't figure out how to get the real address, don't bother ]
"The religions of the future will resemble science fiction." -- Dr. Timothy
Leary
the utility 'passwd' explicitly opens /dev/tty for reading. That's done
for security reasons.
If you don't have source to 'passwd' you have to work around , one
way might be "expect" (look at learest pd-archive). I also remember
this done in perl but i don't remember where ---
> Thanks!
--
Peter Håkanson
IPSec Sverige (At the Riverside of Gothenburg, home of Volvo)
Sorry about my e-mail address, but i'm trying to keep spam out.
Remove "icke-reklam" and it works.
> I want to write a /bin/sh script that takes and argument and completes the
> passwd username command. Does anyone know how to go about this? I have the
> script taking the arguments and calling passwd, but it just waits for me to
> enter a password. Thanks in Advance.
passwd needs a terminal to read from.
do a:
mkfifo z
then write/read to z the same you would do interactively:
passwd cgd < z &
read < z
echo cgdcgd > z
read < z
echo cgdcgd > z
hint: probably this would not work as is-- this is best
done in C, with a select looping on z, for read/write
data when it can... this way (as is) it might block
on a write, and (most probably) on a read
--
PORTUGAL ROBBED AT EURO2000: http://cgd.teleweb.pt
This won't work at all, since a FIFO is not a terminal. Anyway,
`passwd' doesn't care what its standard input and output are, it opens
/dev/tty and talks to the user there. To intercept this, you'll need
to use something like `expect', which emulates a terminal.
--
Nate Eldredge
neld...@hmc.edu
As a curiosity thing, is expect-like behavior impossible from a Bourne
or POSIX shell? Another one that has stymied me is trying to write
a rudimentry pager in a sh script. Comments?
Rick Hohensee
ri...@clienux.com
To get expect-like behaviour, you need to interpose a pseudo-tty
between the controlling program and the program which insists on
talking to a tty. Shells do not give you the access you need to
the ioctl() calls which control ptys, and so you need the help
of some other program, such as:
expect
perl
pty
ssh
rsh
telnet
> Another one that has stymied me is trying to write
>a rudimentry pager in a sh script. Comments?
input_file=$1
pagelen=24
cur=1
while read line; do
cur=`expr $cur + 1`
if [ $cur -ge $pagelen ]; then
printf "Press return to continue..."
read junk </dev/tty
fi
printf "%s\n" "$line"
done < "$input_file"
--Ken Pizzini
this works if passwd behaves like the linux passwd, else is just
a matter of polling a bit the WAITs.
it is called as
do_chg_pass(user, newpass);
and must be run by root
.......
#define PASSWD "/usr/bin/passwd"
static int
openpty(int *amaster, int *aslave)
{
static char line[] = "/dev/ptyXX";
register const char *cp1, *cp2;
register int master, slave;
for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
line[8] = *cp1;
for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
line[5] = 'p';
line[9] = *cp2;
if ((master = open(line, O_RDWR, 0)) == -1) {
if (errno == ENOENT)
return (-1); /* out of ptys */
} else {
line[5] = 't';
if ((slave = open(line, O_RDWR, 0)) != -1) {
*amaster = master;
*aslave = slave;
return (0);
}
(void) close(master);
}
}
}
errno = ENOENT; /* out of ptys */
return (-1);
}
static int
do_chg_pass(char *user, char *pass)
{
int master, slave;
fd_set rfds;
struct timeval tv;
char c;
int status;
if (openpty(&master, &slave) == -1) {
/* perror("openpty"); */
return 3;
}
switch (fork()) {
case -1:
/* perror("fork"); */
return 3;
case 0:
/*
* child
*/
(void) close(master);
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
close(slave);
setuid(0);
execl(PASSWD, "passwd", user, (char *)0);
return (0);
}
/*
* parent
*/
(void) close(slave);
#define WAIT(usecs) \
tv.tv_sec = 0; \
tv.tv_usec = usecs; \
FD_ZERO(&rfds); \
FD_SET(master, &rfds); \
while (select(master+1, &rfds, 0, 0, &tv)>0 && read(master, &c, 1)>0) {\
tv.tv_sec = 1; \
tv.tv_usec = 0; \
FD_ZERO(&rfds); \
FD_SET(master, &rfds); \
}
WAIT(500000);
write(master, pass, strlen(pass));
c = '\n';
write(master, &c, 1);
WAIT(500000);
write(master, pass, strlen(pass));
c = '\n';
write(master, &c, 1);
WAIT(500000);
return 0;
wait(&status);
if (WIFEXITED(status)) {
return 0;
}
return 3;
|||APPLAUSE|||
I hadn't seen the done < "$input_file" before. I have been using
"while read" on stdin lately though. Hmmmmm, that might allow input
on other fd's too.....
Rick Hohensee
ri...@cLIeNUX.com
> --Ken Pizzini
I forgot a crucial line here:
cur=1
> fi
> printf "%s\n" "$line"
>done < "$input_file"
--Ken Pizzini