home *** CD-ROM | disk | FTP | other *** search
- /*
- ** 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];
- }
-