[Coco] Uemacs
Jeff Teunissen
deek at d2dc.net
Tue Feb 15 13:25:28 EST 2022
On Mon, Feb 14, 2022 at 7:56 PM Bill Gunshannon
<bill.gunshannon at hotmail.com> wrote:
>
> On 2/13/22 21:24, Jeff Teunissen wrote:
> > On Fri, Feb 11, 2022 at 12:42 PM Bill Gunshannon
[snip]
> > Huh, that's interesting. In that case, I wonder why it's broken.
>
> Didn't really take the time to look. Would rather figure out what
> it does and re-write it in C. :-)
Here's my version. It requires the DCC compiler instead of the classic
Microware compiler, because it uses unsigned char and some C++-style
comments, but it does build on a CoCo. :)
----->8----- cut here -----8<-----
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <sgstat.h>
#include <signal.h>
#include <password.h>
direct char namebuf[PWNSIZ];
direct char passbuf[PWPSIZ];
#define LOGIN_RETRIES 3
#define FAIL_DELAY 2
#define prompt(x) \
writeln (STDOUT_FILENO, x, sizeof (x) - 1)
/*
These arrays cause the program to use slightly more memory than using
pointers to constant strings, but they allow us to use 'sizeof' to get
their lengths instead of 'strlen', which means no math being done at
run-time.
*/
char LogPrompt[] = "Login: ";
char PassPrompt[] = "Password: ";
char NoPass[] = "Login incorrect\n";
char Bye[] = "Goodbye.\n";
char NewLine[] = "\n";
char Sorry[] = "can't open password file.\n";
char Dir[] = "can't find home directory; will use current.\n";
char XDir[] = "can't find exec directory; will use current.\n";
direct char saved = 0;
direct struct sgbuf savedSet, newSet;
direct char *username = NULL;
direct char motdbuf[120]; /* Buffer for message of the day */
trylogin();
chaincmd();
getstr();
trap(sig)
{
rstEcho();
exit(sig);
}
noEcho()
{
if (!saved && -1 != _gs_opt (STDIN_FILENO, &savedSet)) {
unsigned char i;
unsigned char *old = (char *)&savedSet;
register unsigned char *new = (char *)&newSet;
for (i = 0; i < sizeof (struct sgbuf); i++)
*new++ = *old++;
newSet.sg_echo = 0;
saved = 1;
}
_ss_opt (STDIN_FILENO, &newSet);
}
rstEcho()
{
if (saved) _ss_opt (STDIN_FILENO, &savedSet);
}
getuser()
{
prompt (LogPrompt);
getstr (namebuf, sizeof (namebuf) - 1);
if (*namebuf)
return namebuf;
return NULL;
}
getstr(buf, siz)
char buf[];
int siz;
{
register char *i = buf;
readln (STDIN_FILENO, buf, siz);
while (*i && *i != '\n')
++i;
*i = '\0';
}
getpass()
{
noEcho();
prompt (PassPrompt);
getstr (passbuf, sizeof (passbuf) - 1);
prompt (NewLine);
rstEcho();
return passbuf;
}
main (argc, argv)
int argc;
char **argv;
{
register int i;
intercept (trap);
asetuid (0); // We're gonna need to be root a lot
if (argc > 1) { /* called with username, prefill it once */
username = argv[1];
} else { /* No username, print banner */
int fd;
if (-1 != (fd = open ("/DD/SYS/banner", O_RDONLY))) {
while (readln (fd, motdbuf, sizeof (motdbuf)))
writeln (STDOUT_FILENO, motdbuf, sizeof (motdbuf));
close (fd);
}
}
for (i = 0; i < LOGIN_RETRIES; i++) {
trylogin (username);
// if we even get here, it's a failure
sleep (FAIL_DELAY);
prompt (NoPass);
username = NULL;
}
prompt (Bye);
exit (1);
}
trylogin(name)
char *name;
{
register PWENT *entry;
char *pass;
int fd;
if ((!name || !*name) && !(name = getuser()))
return;
if (!(pass = getpass()))
return;
if (entry = getpwnam (name)) {
if (*(entry->upw) == '*' || strucmp (pass, entry->upw))
goto done;
/* matched */
setpr (getpid (), atoi (entry->upri)); // set priority, user inherits
setuid (atoi (entry->uid)); // set new uid
if (-1 == chdir (entry->udat))
prompt (Dir);
if (-1 == chxdir(entry->ucmd))
prompt (XDir);
/* Print MOTD */
if (-1 != (fd = open ("/DD/SYS/motd", O_RDONLY))) {
while (readln (fd, motdbuf, sizeof (motdbuf)))
writeln (STDOUT_FILENO, motdbuf, sizeof (motdbuf));
close (fd);
}
chaincmd (entry->ujob);
exit (1);
}
done:;
endpwent();
}
chaincmd (cmd)
char *cmd;
{
char buf[80];
char *args;
register char *tmp = buf;
/* First, fill buf from cmd */
while (*cmd)
*tmp++ = *cmd++; // poor man's strcpy
*tmp = '\0';
/* Now, terminate the "program' at the first space */
tmp = buf; // back to the beginning
while (*++tmp != ' ') ; // find the first space
*tmp++ = '\0'; // turn it into a nul
args = tmp;
/*
* now args points at the start of the arguments, but it needs to end
* with a newline, not a nul...
*/
while (*++tmp) ; // point tmp at the NUL at the end
*tmp++ = '\n';
*tmp = '\0';
/*
* By happy accident, the difference between tmp and args should now be
* exactly the length of the parameters, so _again_ we don't need strlen.
*/
chain (buf, tmp - args, args, 1, 1, 0);
}
More information about the Coco
mailing list