home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume3
/
send
/
send.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-03
|
13KB
|
635 lines
/*
** send.c
**
** Written by: Keith Gabryelski (ag@elgar.UUCP)
**
** Released into public domain June 14, 1988.
** Please keep this header.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utmp.h>
#include <pwd.h>
#include <errno.h>
extern errno;
extern struct passwd *getpwuid(), *getpwnam();
extern FILE *fopen();
extern char *getlogin(), *strrchr(), *ctime(), *malloc(), *realloc();
extern char *ttyname(), *strcpy(), *strncpy(), *strcat();
extern long time();
extern char *sys_errlist[];
extern int sys_nerr;
extern void setutent();
#undef TRUE
#undef FALSE
#define TRUE 1
#define FALSE 0
#define UNUSED -1
#define NORMAL 0
#define FAST 1
#define SENDS_FILENAME "/.sends" /* must have the '/' */
#define DEAD_SEND_FILENAME "/dead.send" /* must have the '/' */
#define MESSAGE_SEPARATOR 0x1F
char *puterr(), *get_typed_message(), *cat_message(), *myfgets();
char *get_last_sender();
int reply(), send(), shout();
struct
{
char *name; /* Command name. */
int (*function)(); /* Function to use. */
int type; /* Parameters. */
char *text; /* First word in header.*/
}
command_table[] =
{
{"fr", reply, FAST, "Reply"},
{"freply", reply, FAST, "Reply"},
{"fs", send, FAST, "Message"},
{"fsend", send, FAST, "Message"},
{"reply", reply, NORMAL, "Reply"},
{"send", send, NORMAL, "Message"},
{"shout", shout, NORMAL, "Shout"},
{NULL, }
};
int argc, uid;
char **argv, *progname;
char login_name[] = " \0", /* eight chars plus nul */
tty_name[] = " \0"; /* twelve chars plus a nul */
char *
mymalloc(size)
unsigned size;
{
char *p;
if ((p = malloc(size)) == NULL)
{
(void) fprintf(stderr, "%s: Out of memory.\n", progname);
exit(-1);
}
return p;
}
char *
myrealloc(p, size)
char *p;
unsigned size;
{
if (p == NULL)
{
if ((p = malloc(size)) == NULL)
{
(void) fprintf(stderr, "%s: Out of memory.\n", progname);
exit(-1);
}
}
else if ((p = realloc(p, size)) == NULL)
{
(void) fprintf(stderr, "%s: Out of memory.\n", progname);
exit(-1);
}
return p;
}
main(largc, largv)
int largc;
char **largv;
{
char *ptr;
int i;
struct passwd *pt;
progname = *largv++; --largc;
argv = largv; argc = largc;
uid = getuid();
pt = getpwuid(uid);
if ((ptr = getlogin()) == NULL)
if ((ptr = pt->pw_name) == NULL)
ptr = "somebody"; /* can't figure this guy out */
(void) strncpy(login_name, ptr, 8);
if ((ptr = ttyname(0)) == NULL)
strcpy(tty_name, "tty??");
else
strncpy(tty_name, ((ptr= strrchr(ptr, '/')) ? ptr+1 : "tty??"), 12);
i = 0;
while (command_table[i].name != NULL)
if (strcmp(progname, command_table[i].name))
++i;
else
break;
if (command_table[i].name == NULL)
send(NORMAL, "Message");
else
(*command_table[i].function)(command_table[i].type,
command_table[i].text);
exit(0);
}
/*
** reply --
** Reply to a previously sent message. This routine uses the
** (from) user name of the last message sent as the user to
** send a message to.
*/
reply(type, text)
int type;
char *text;
{
char **send_to_list = (char **)mymalloc(0);
char *message;
/*
** make send_to_list initially have one element -- NULL.
**
** Even though only one user is ever gonna get a message,
** I still use the add_to_list() routine.
*/
send_to_list = (char **)myrealloc(send_to_list, sizeof(char *));
send_to_list[0] = NULL;
add_to_list(&send_to_list, get_last_sender());
message = get_typed_message();
send_message(send_to_list, message, type, text);
}
/*
** send - generic send-a-message-to-one-or-more-users routine.
**
**
**
*/
send(type, text)
int type;
char *text;
{
char **send_to_list = (char **)mymalloc(0);
char *message;
/*
** make send_to_list initially have one element -- NULL.
**
*/
send_to_list = (char **)myrealloc(send_to_list, sizeof(char *));
send_to_list[0] = NULL;
if (argc < 1)
{
fprintf(stderr, "%s: usage: %s user1, [user2,] [...,] [message]\n",
progname, progname);
exit(-1);
}
while (*argv != NULL)
{
--argc;
if ((*argv)[strlen(*argv)-1] == ',')
{
(*argv)[strlen(*argv)-1] = '\0';
add_to_list(&send_to_list, *argv++);
}
else
{
add_to_list(&send_to_list, *argv++);
break;
}
}
message = get_typed_message();
send_message(send_to_list, message, type, text);
}
/*
** shout -- Send a message to all logged in users.
**
**
*/
shout(type, text)
int type;
char *text;
{
char **send_to_list = (char **)mymalloc(0);
char *message;
struct utmp *getutent(), *ut;
/*
** make send_to_list initially have one element -- NULL.
**
*/
send_to_list = (char **)myrealloc(send_to_list, sizeof(char *));
send_to_list[0] = NULL;
setutent();
while ((ut = getutent()) != (struct utmp *)NULL)
if (ut->ut_type == USER_PROCESS)
add_to_list(&send_to_list, ut->ut_line);
message = get_typed_message();
send_message(send_to_list, message, type, text);
}
/*
** get_typed_message() --
** Get arguments for a message of the command line
** and take input from stdin if the last argument
** is "-" or no message was given on the command
** line.
*/
char *
get_typed_message()
{
char *buffer = mymalloc(1);
int old_argc;
*buffer = '\0';
old_argc = argc;
while (argc > 0 && !(argc == 1 && !strcmp(*argv, "-")))
{
buffer = cat_message(buffer, *argv++);
buffer = cat_message(buffer, " ");
--argc;
}
if (argc || !old_argc)
{
char *line = mymalloc(BUFSIZ);
while ((line = myfgets(line, BUFSIZ, stdin)) != NULL)
buffer = cat_message(buffer, line);
}
/*
** That extra <cr> or ' '. ack...
*/
if (buffer[strlen(buffer)-1] == '\n' || buffer[strlen(buffer)-1] == ' ')
buffer[strlen(buffer)-1] = '\0';
return buffer;
}
char *
myfgets(buffer, size, stream)
char *buffer;
int size;
FILE *stream;
{
int c, length = 0;
while ((c = getc(stream)) != EOF && c != '\n' && (length-1) < size)
if (c >= ' ')
buffer[length++] = c;
if (c == '\n')
buffer[length++] = c;
buffer[length++] = '\0';
return c == EOF ? NULL : buffer;
}
char *
cat_message(buffer, line)
char *buffer, *line;
{
buffer = myrealloc(buffer, strlen(buffer) + strlen(line) + 1);
strcat(buffer, line);
return buffer;
}
char *
get_last_sender()
{
char *ptr, *sends_filename = mymalloc(0);
char dummy[50];
static char name[50];
int c, n;
struct passwd *pt;
FILE *fp;
pt = getpwuid(uid);
if ((ptr = pt->pw_dir) != NULL)
{
sends_filename = myrealloc(sends_filename, strlen(ptr) +
sizeof(SENDS_FILENAME) + 1);
strcpy(sends_filename, ptr);
strcat(sends_filename, SENDS_FILENAME);
if ((fp = fopen(sends_filename, "r")) == (FILE *)NULL)
{
fprintf(stderr, "%s: No reply possible, can't open %s (%s).\n",
progname, sends_filename, puterr(errno));
exit(-1);
}
*name = '\0';
while (fscanf(fp, "[%s %s %s (%s", dummy, dummy, dummy,
name) == 4)
while ((c = getc(fp)) != MESSAGE_SEPARATOR && c != EOF)
;
fclose(fp);
if (name[strlen(name)-1] == ')')
name[strlen(name)-1] = '\0';
if (*name == '\0')
{
fprintf(stderr, "%s: no sends.\n", progname);
exit(-1);
}
}
else
{
fprintf(stderr, "%s: No reply possible, no home directory.\n",
progname);
exit(-1);
}
return name;
}
send_message(user_list, message, type, text)
char **user_list, *message;
int type;
char *text;
{
char *date_text, *ptr, *sends_filename = mymalloc(0);
char **sent_to_list = (char **)mymalloc(0);
char **sends_list = (char **)mymalloc(0);
int sendit = TRUE, sent = FALSE, failed = FALSE, need_crlf = FALSE;
long clock[1];
struct utmp *getutent(), *ut;
struct passwd *pt;
struct stat stbuf;
FILE *fp;
static char device[] = "/dev/ \0";
/* setup null sent_to_list */
sent_to_list = (char **)myrealloc(sent_to_list, sizeof(char *));
sent_to_list[0] = NULL;
sends_list = (char **)myrealloc(sends_list, sizeof(char *));
sends_list[0] = NULL;
/* get the date without a terminating <cr> */
clock[0] = time((long *)0);
date_text = ctime(clock);
date_text[24] = '\0';
/* find user/tty in utmp */
while (*user_list != NULL)
{
setutent();
sendit = UNUSED;
sent = FALSE;
while ((ut = getutent()) != (struct utmp *)NULL)
{
if ((ut->ut_type == USER_PROCESS) &&
((!strncmp(ut->ut_user, *user_list, 8)) ||
(!strncmp(ut->ut_line, *user_list, 12))))
{
sendit = TRUE;
if (add_to_list(&sent_to_list, ut->ut_line))
{
sent = TRUE;
break;
}
strncpy(device+5, ut->ut_line, 12);
if (uid != 0)
{
if (stat(device, &stbuf) == -1)
{
fprintf(stderr, "%s: Couldn't stat %s (%s).\n",
progname, device, puterr(errno));
sendit = FALSE;
failed = TRUE;
}
else
if (!stbuf.st_mode&2)
{
fprintf(stderr,
"[%s/%s]: Is not receiving sends.\n",
ut->ut_user, ut->ut_line);
sendit = FALSE;
failed = TRUE;
}
}
/* open device and send the message */
if (sendit)
{
if ((fp = fopen(device, "w")) == (FILE *)NULL)
fprintf(stderr, "%s: could not open %s (%s).\n",
progname, device, puterr(errno));
else
{
if (type&FAST)
fprintf(fp, "\007\n[%s/%s: %s]\n", login_name,
tty_name, message);
else
fprintf(fp, "\007\n[%s from %s (%s) %s]\n%s\n",
text, login_name, tty_name, date_text,
message);
printf("[%s/%s] ", ut->ut_user, ut->ut_line);
need_crlf = sent = TRUE;
fclose(fp);
/* write send to ~user/.sends file */
if (!add_to_list(&sends_list, ut->ut_user))
{
pt = getpwnam(ut->ut_user);
if ((ptr = pt->pw_dir) != NULL)
{
sends_filename =
myrealloc(sends_filename, strlen(ptr) +
sizeof(SENDS_FILENAME) + 1);
strcpy(sends_filename, ptr);
strcat(sends_filename, SENDS_FILENAME);
if ((fp = fopen(sends_filename, "a+")) !=
(FILE *)NULL)
fprintf(fp, "[%s from %s (%s) %s]\n%s\n%c",
text, login_name, tty_name,
date_text, message,
MESSAGE_SEPARATOR);
fclose(fp);
}
}
}
}
}
}
if (!sent)
{
failed = TRUE;
if (sendit == UNUSED)
{
/*
** Decide what the user tried to type in. Was it a user
** who isn't logged in or maybe a tty device that no user
** is logged on to or maybe a mistyped username.
*/
if ((pt = getpwuid(*user_list)) == (struct passwd *)NULL)
{
int status;
strncpy(device+5, *user_list, 12);
status = stat(device, &stbuf);
if (status == -1 || !stbuf.st_mode&S_IFCHR)
fprintf(stderr, "%s: no user %s.\n", progname,
*user_list);
else
fprintf(stderr, "%s: no user logged on device %s.\n",
progname, *user_list);
}
else
fprintf(stderr, "%s: %s not logged in.\n", progname,
*user_list);
}
}
++user_list;
}
if (failed)
{
char *dead_filename = malloc(0);
pt = getpwuid(uid);
if ((ptr = pt->pw_dir) == NULL)
{
dead_filename = myrealloc(dead_filename, sizeof("/tmp/") +
sizeof(login_name) +
sizeof(DEAD_SEND_FILENAME) + 1);
strcpy(dead_filename, "/tmp/");
strcat(dead_filename, login_name);
strcat(dead_filename, DEAD_SEND_FILENAME);
}
else
{
dead_filename = myrealloc(dead_filename, strlen(ptr) +
sizeof(DEAD_SEND_FILENAME) + 1);
strcpy(dead_filename, ptr);
strcat(dead_filename, DEAD_SEND_FILENAME);
}
if ((fp = fopen(dead_filename, "a+")) != (FILE *)NULL)
{
fprintf(fp, "[%s from %s (%s) %s]\n%s\n%c", text, login_name,
tty_name, date_text, message, MESSAGE_SEPARATOR);
fprintf(stderr, "%s: message copied to %s.\n", progname,
dead_filename);
}
fclose(fp);
free(dead_filename);
}
if (need_crlf)
putchar('\n');
free(sends_filename);
}
add_to_list(list, name)
char ***list, *name;
{
register int i;
for (i = 0; (*list)[i] != NULL; ++i)
if (!strcmp((*list)[i], name))
return TRUE;
*list = (char **)myrealloc(*list, sizeof(char *) * (i + 2));
(*list)[i] = mymalloc(strlen(name)+1);
strcpy((*list)[i], name);
(*list)[i+1] = NULL;
return FALSE;
}
/*
**
**free_list(list)
**char **list;
**{
** register int i;
**
** for (i = 0; list[i] != NULL; ++i)
** free(list[i]);
**
** free(list);
**}
*/
char *
puterr(error)
int error;
{
static char qwerty[42];
(void) sprintf(qwerty, "Unknown error %d", error);
return ((unsigned)error >= sys_nerr) ? qwerty : sys_errlist[error];
}