|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6322 (0x18b2)
Types: TextFile
Notes: UNIX file
Names: »write.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/write.c«
/*
* Rec'd from Lauren Weinstein, 7-16-84.
* Write to another user
* on the system.
* This is setuid in order to
* use execute permission on the
* terminal to allow/disallow writes.
*
* Compile -s -n -i
*/
#include <stdio.h>
#include <utmp.h>
#include <signal.h>
#include <sys/stat.h>
#include <sgtty.h>
#define FALSE 0
#define TRUE 1
#define NSYSC 150 /* Maximum system call line */
FILE *tf;
struct stat sb;
struct sgttyb sgttyb, sgttys; /* for user tty modes */
struct sgttyb sgttyd; /* for dest tty modes */
struct tchars tchars; /* for determining EOF char */
char sighup, sigquit, sigint; /* signal change flags */
int eofmark; /* EOF marker */
char dtty[40] = "/dev/";
int conopen; /* TRUE if connection open */
int status; /* exit status */
int dcrtmode; /* non-zero for dest tty crt mode */
int ucrtmode; /* non-zero for user tty crt mode */
int istty; /* TRUE if input is a tty */
int quit();
char *getutmp();
char *getlogin();
char *ttyname();
char crtwarn[] =
"Warning: One or both ttys is not a screen-oriented device.\n\
Backspacing/character erase will not function properly...\n";
main(argc, argv)
char **argv;
{
char *totty, *touname;
char *fromtty, *fromuname;
char crtmode = 0; /* TRUE if both ttys are crt's */
register int c;
register int nlf = 1;
if (argc == 3)
totty = argv[2];
else {
if (argc != 2)
usage();
totty = NULL;
}
touname = argv[1];
gtty(0, &sgttyb); /* get tty modes into buffer */
if (sgttyb.sg_flags & CRT) /* crt mode on user tty? */
ucrtmode++; /* yes */
gtty(0, &sgttys); /* save copy of original modes */
fromuname = getlogin();
totty = getutmp(totty, touname);
strcat(dtty, totty); /* build full ttyname */
if ((fromtty = ttyname(fileno(stderr))) != NULL) {
stat(fromtty, &sb);
if ((sb.st_mode & S_IEXEC) == 0)
fprintf(stderr, "Warning: no reply possible\n");
fromtty += 5; /* Skip over `/dev/' */
}
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
{ signal(SIGINT, &quit); /* catch ints */
sigint++; /* flag we're catching ints */
}
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
{ signal(SIGHUP, &quit); /* catch hangups */
sighup++; /* flag */
}
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
{ signal(SIGQUIT, &quit); /* catch quits */
sigquit++;
}
ioctl(0, TIOCGETC, &tchars); /* get char settings */
setup(touname, dtty);
if (isatty(0)) /* input a tty? */
{ istty = TRUE; /* yes */
eofmark = tchars.t_eofc; /* set EOF marker */
}
else
eofmark = EOF; /* set EOF marker */
if (!(crtmode = dcrtmode&ucrtmode)) /* check for both crt's */
if (!ucrtmode && istty) /* input not crt and not tty? */
fprintf(stderr, crtwarn); /* yes, warn user */
conopen = TRUE; /* flag connection open */
sgttyb.sg_flags |= CBREAK; /* want cbreak mode */
stty(0, &sgttyb); /* set new mode (no flush) */
/*
* Turn off setuid privileges.
*/
setuid(getuid());
fprintf(tf, "\r\n\7Message from %s (%s) ...\r\n", fromuname, fromtty);
printf("\r\nUser %s has been notified ...\r\n", touname);
while ((c = getchar()) != eofmark) { /* continue until end of file */
if (nlf && c=='!') {
callsys();
continue;
}
if (c == '\n')
nlf = 1;
else
nlf = 0;
putc(c, tf);
if (c == '\b' && crtmode) /* backspace and crt's? */
{ putc(' ', stdout); /* erase local char */
putc('\b', stdout);
putc(' ', tf); /* erase dest char */
putc('\b', tf);
}
}
quit();
}
callsys()
{
char sysline[NSYSC];
register char *cp;
register int c;
cp = sysline;
while ((c = getchar()) != '\n')
if (cp < &sysline[NSYSC-1])
*cp++ = c;
*cp = '\0';
signal(SIGINT, SIG_IGN); /* ignore ints */
signal(SIGHUP, SIG_IGN); /* hups */
signal(SIGQUIT, SIG_IGN); /* and quits */
stty(0, &sgttys); /* restore original modes */
system(sysline); /* fork child command */
stty(0, &sgttyb); /* back to special modes */
if (sigint) /* restore int status */
signal(SIGINT, &quit);
if (sighup) /* hup */
signal(SIGHUP, &quit);
if (sigquit) /* quit */
signal(SIGQUIT, &quit);
printf("!\n");
}
/*
* Check whether or not writes are
* allowed to this terminal.
*/
setup(u, t)
char *u, *t;
{
register char abortf = 0;
register char c;
if ((tf = fopen(t, "w")) == NULL)
fprintf(stderr, "write: cannot open %s\n", t);
if (gtty(fileno(tf), &sgttyd) >= 0) /* stat dest tty */
if (sgttyd.sg_flags & CRT) /* crt mode on dest tty? */
dcrtmode++;
if (fstat(fileno(tf), &sb) < 0) {
fprintf(stderr, "write: can't write to %s\n", u);
quiterr();
}
if ((sb.st_mode&S_IEXEC) == 0) {
if (getuid() == 0) /* is our real uid su? */
{ fprintf(stderr,
"User \"%s\" is denying messages. Override? ", u);
if ((c = getchar()) != 'y')
abortf++; /* flag abort */
while (c != EOF && c != '\n') /* flush remaining input */
c = getchar();
if (abortf) /* override requested? */
return; /* allow write */
else
quit();
}
fprintf(stderr, "write: no permission to write to %s\n", u);
quiterr();
}
}
/*
* Return the tty for the specified
* username and possibly tty
* from the utmp file.
*/
char *
getutmp(t, u)
char *t, *u;
{
register FILE *fp;
static struct utmp ut;
if ((fp = fopen("/etc/utmp", "r")) == NULL) {
fprintf(stderr, "write: /etc/utmp not accessible\n");
quiterr();
}
while (fread(&ut, sizeof ut, 1, fp) == 1) {
if (strncmp(ut.ut_name, u, DIRSIZ) != 0)
continue;
if (t != NULL)
if (strncmp(ut.ut_line, t, 8) == 0) {
fclose(fp);
return (t);
} else
continue;
ut.ut_line[8] == '\0';
fclose(fp);
return (ut.ut_line);
}
if (t == NULL)
fprintf(stderr, "write: %s not logged in\n", u);
else
fprintf(stderr, "write: %s not logged onto %s\n", u, t);
quiterr();
}
quit()
{
if (conopen) /* if connection open */
{ stty(0, &sgttys); /* normal mode */
fprintf(tf, "EOT\n");
fclose(tf); /* close connection */
}
exit(status);
}
quiterr()
{
status = 1; /* exit with error status */
quit();
}
usage()
{
fprintf(stderr, "Usage: write username [ttyname]\n");
quit(1);
}