This is write.c in view mode; [Download] [Up]
/* write.c:
*
* these routines are used for writing to users
*
* (c) Copyright 1988, 1989, 1990 Jim Frost. All Rights Reserved. Please see
* the accompanying file "Copyright" for more information.
*/
#include "Copyright"
#include "config.h"
#include "msend.h"
extern int errno;
#ifdef SECURE_PORT
extern short notsecure;
#endif
/* this writes to the tty specified in si and saves the message in spool
*/
static int ttywrite(si)
struct simsg *si;
{ FILE *f;
char fname[MAXFILENAME];
int uid;
/* try to write to user's tty
*/
sprintf(fname,"/dev/%s",si->ttty);
if ((f= fopen(fname,"w")) == NULL)
if (errno == EACCES)
return(RE_NOMSGS);
else
return(RE_SYSERR);
#ifdef SECURE_PORT
if (notsecure)
fprintf(f,"\r\n\007[Bogus? %s]\r\n",si->msg);
else
#endif
fprintf(f,"\r\n\007\007\007[%s]\r\n\007\007",si->msg);
fclose(f);
/* save the message in the spool for "huh" option
*/
if (getuid() == ROOTUID) {
if ((uid= getid(si->taddr)) < 0) /* write to file as if we were user */
return(RE_NOUSER);
seteuid(uid);
}
#ifdef SPOOLDIR
sprintf(fname,"%s/%s",SPOOLDIR,si->taddr);
#else
sprintf(fname,"%s/.msendmsgs",gethome(si->taddr));
#endif
if ((f= fopen(fname,"a")) != NULL) {
flock(fileno(f),LOCK_EX);
fprintf(f,"[%s]\n",si->msg);
flock(fileno(f),LOCK_UN);
fclose(f);
}
if (getuid() == ROOTUID)
seteuid(DAEMONUID);
return(RE_OK);
}
void broadcast(si)
struct simsg *si;
{ char s[80];
struct utmp *u;
sprintf(s,"\007\007\007Broadcast message %s\007\007",si->msg); /* log it! */
error(s);
/* loop for every utmp entry and try to write. ignore any
* errors returned by ttywrite. we have to implement the
* entire write command here or else we get an infinite
* loop on the first utmp entry.
*/
while (u= getutent()) {
#ifdef SYSVUTMP
if (u->ut_type != USER_PROCESS)
continue;
#endif
if (strcmp(u->ut_name,"")) {
sprintf(si->ttty,u->ut_line);
sprintf(si->taddr,u->ut_name);
ttywrite(si);
}
}
endutent();
}
/* single user
*/
int writeuser(si)
struct simsg *si;
{ struct utmp *u; /* utmp entry */
struct stat stb;
struct rimsg ri;
char *home;
char ttyname[sizeof("/dev/")+MAXTTY+1];
char token[MAXTOKEN+1];
char fname[MAXFILENAME+1];
char line[MAXLINE+1];
FILE *f;
time_t ltime;
int ttystat;
int notfound;
int allttys;
int forward;
int fwderr;
int ttyerr;
int uid;
/* send to particular tty
*/
if (si->mode & SM_TTY) {
/* look up user of that tty.
*/
ttystat= RE_SYSERR;
while (u= getutent())
if (!strcmp(u->ut_line,si->ttty)) {
strcpy(si->taddr,u->ut_name);
strcpy(si->ttty,u->ut_line);
ttystat= ttywrite(si);
break;
}
endutent();
if (ttystat == RE_SYSERR)
errno= ENODEV; /* error message for user */
return(ttystat);
}
/* open user's options file and see if they want some special
* propagation
*/
allttys= 0;
forward= 0;
fwderr= RE_OK;
if ((home= gethome(si->taddr)) == NULL)
return(RE_NOUSER);
if (getuid() == ROOTUID) {
if ((uid= getid(si->taddr)) < 0)
return(RE_NOUSER);
seteuid(uid);
}
sprintf(fname,"%s/.msendrc",home);
if ((f= fopen(fname,"r")) != NULL) {
while (fgets(line,MAXLINE,f) != NULL) {
sscanf(line,"%s",token);
/* tty options
*/
if (!strcmp(token,"allttys"))
allttys= 1;
else if (!strcmp(token,"write-to-tty")) {
sscanf(line,"%*s %s",si->ttty);
ttywrite(si);
forward= 1; /* same idea as forwarding */
}
/* forwarding options. note that we return the first error that
* we get when forwarding so the user has some idea that something
* went wrong. compound errors will be lost. we ignore obvious
* host loops.
*/
else if (!strcmp(token,"forward-to-user")) {
sscanf(line,"%*s %s",si->taddr);
if ((striphost(si->taddr,si->tohost)) && (!fwdloop(si->tohost))) {
si->fwdcount++;
forward= 1;
sendmessage(si,&ri,si->mode);
if (fwderr == RE_OK)
fwderr= ri.h.errno;
}
}
else if (!strcmp(token,"forward-to-tty")) {
sscanf(line,"%*s %s %s",si->ttty,si->taddr);
if ((striphost(si->taddr,si->tohost)) && (!fwdloop(si->tohost))) {
forward= 1;
si->fwdcount++;
sendmessage(si,&ri,si->mode);
if (fwderr == RE_OK)
fwderr= ri.h.errno;
}
}
else if (!strcmp(token,"write-and-forward-to-user")) {
sscanf(line,"%*s %s",si->taddr);
if ((striphost(si->taddr,si->tohost)) && (!fwdloop(si->tohost))) {
si->fwdcount++;
sendmessage(si,&ri,si->mode);
if (fwderr == RE_OK)
fwderr= ri.h.errno;
}
}
}
fclose(f);
if (forward)
return(fwderr);
}
if (getuid() == ROOTUID)
seteuid(DAEMONUID);
/* send to least idle user or all writable ttys, depending on mode.
*/
ltime= (time_t)0;
notfound= 1;
ttyerr= RE_OK;
while (u= getutent()) {
if (!strcmp(u->ut_name,si->taddr)) { /* match user */
sprintf(ttyname,"/dev/%s",u->ut_line);
if (stat(ttyname,&stb) != -1) {
notfound= 0;
if (stb.st_mode & 022) /* see if we have permission */
if (allttys) {
/* write to every possible tty
*/
strcpy(si->ttty,u->ut_line);
if (ttyerr != RE_OK)
ttywrite(si);
else
ttyerr= ttywrite(si);
}
else {
/* look for least idle terminal
*/
if (!ltime) {
ltime= stb.st_mtime;
strcpy(si->ttty,u->ut_line);
}
else if (stb.st_mtime > ltime) { /* less idle */
ltime= stb.st_mtime;
strcpy(si->ttty,u->ut_line);
}
}
}
}
}
endutent();
if (allttys)
return(ttyerr);
if (notfound)
return(RE_NOTTHERE);
else if (!ltime)
return(RE_NOMSGS);
return(ttywrite(si));
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.