home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
-
- This file is part of advise.
-
- advise is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the advise General Public
- License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- advise, but only under the conditions described in the
- advise General Public License. A copy of this license is
- supposed to have been given to you along with advise so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies. */
-
- /*
- ** Author: Keith Gabryelski (ag@amix.commodore.com)
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <stropts.h>
- #include <poll.h>
- #include <sys/stream.h>
- #include <errno.h>
- #include <utmp.h>
- #include <pwd.h>
- #include <termios.h>
- #include <string.h>
- #include <ctype.h>
- #include "advise.h"
-
- #ifdef sun
- extern int optind;
-
- #ifndef CTRL
- #define CTRL(c) ((c)&037)
- #endif /* !CTRL */
-
- #ifndef EUNATCH
- #define EUNATCH ENOPROTOOPT
- #endif /* ! EUNATCH */
-
- #endif /* sun */
-
- extern char *optarg;
-
- #define max(a,b) ((a)>(b)?(a):(b))
-
- static struct module_list
- {
- char *name; /* name of module */
- struct module_list *next; /* next module to be pushed */
- } advise_module_list =
- {
- ADVMODNAME, NULL,
- };
-
- #ifdef __STDC__
- #define PR_(x) x
- #else
- #define PR_(x) ()
- #endif /* __STDC__ */
-
- static void usage PR_( (void) ), advise PR_( (char *) );
- static char *strchar PR_( (char) );
- static struct module_list *list_modules PR_( (int, char *));
-
- static int allow_deny_p, allow_deny;
- static int allow_advise_p, allow_advise;
- static int error_flag;
- static int secret, spy, reverse;
- static int meta_character = '~';
- static char *progname;
- static char *module = "ldterm";
-
- #ifdef sun
-
- #ifndef __STDC__
- /*
- * strerror - map error number to descriptive string
- * (stolen from cnews/libfake/strerror.c)
- *
- */
- static char *
- strerror(errnum)
- int errnum;
- {
- extern int sys_nerr;
- extern char *sys_errlist[];
-
- if (errnum > 0 && errnum < sys_nerr)
- return(sys_errlist[errnum]);
- else if (errnum != 0)
- return("unknown error");
- else
- return("no details given");
- }
- #endif /* ! __STDC__ */
-
- static int utmpfd=-1;
-
- void
- endutent(
- #ifdef __STDC__
- void
- #endif /* __STDC__ */
- )
- {
- if(utmpfd!=-1) close(utmpfd);
- utmpfd=-1;
- }
-
- void
- setutent(
- #ifdef __STDC__
- void
- #endif /* __STDC__ */
- )
- {
- endutent();
- utmpfd=open("/etc/utmp", O_RDONLY);
- }
-
- struct utmp *
- getutent(
- #ifdef __STDC__
- void
- #endif /* __STDC__ */
- )
- {
- static struct utmp ut;
- int ret;
-
- if(utmpfd==-1) return(NULL);
- do {
- if(read(utmpfd, &ut, sizeof(ut)) != sizeof(ut)) return(NULL);
- } while(nonuser(ut));
-
- return(&ut);
- }
-
- struct utmp *
- #ifdef __STDC__
- getutline(struct utmp *ut)
- #else
- getutline(ut)
- struct utmp *ut;
- #endif /* __STDC__ */
- {
- struct utmp *utm;
-
- while(utm=getutent())
- if(!strncmp(utm->ut_line, ut->ut_line)) return(utm);
-
- return(NULL);
- }
- #endif /* sun */
-
- int
- #ifdef __STDC__
- main(int argc, char **argv)
- #else
- main(argc, argv)
- char **argv;
- #endif /* __STDC__ */
- {
- int c, error=0;
- struct termios termios;
- struct module_list *modules;
-
- progname = *argv;
-
- while((c = getopt(argc, argv, "ADM:Sardm:s?")) != EOF)
- {
- switch(c)
- {
- case 's':
- spy++;
- break;
-
- case 'r':
- if (!getuid())
- reverse++;
- else
- {
- (void) fprintf(stderr, "%s: -r option only available to the super user\n", progname);
- error_flag++;
- }
- break;
-
- case 'S':
- if (!getuid())
- secret++;
- else
- {
- (void) fprintf(stderr, "%s: -S option only available to the super user\n", progname);
- error_flag++;
- }
- break;
-
- case 'a':
- allow_deny_p++;
- allow_deny=ADVISE_ALLOW;
- allow_advise_p++;
- allow_advise++;
- break;
-
- case 'd':
- allow_advise_p++;
- allow_advise=0;
- break;
-
- case 'A':
- allow_deny_p++;
- allow_deny=ADVISE_ALLOW;
- break;
-
- case 'D':
- allow_deny_p++;
- allow_deny=ADVISE_DENY;
- break;
-
- case 'm':
- meta_character = optarg[0];
- break;
-
- case 'M':
- module = optarg;
- break;
-
- case '?':
- error_flag++;
- break;
- }
-
- if (error_flag)
- {
- usage();
- }
- }
-
- if (allow_advise_p)
- {
- int status = ioctl(0, ADVISE_STATUS, &status);
-
- if (allow_advise && status)
- {
- int advise_module_pushed = 0;
-
- /* Push advise module on stream */
- (void) ioctl(0, TCGETS, &termios);
-
- modules = list_modules(0, module);
-
- advise_module_list.next = modules;
-
- for (modules = &advise_module_list;
- modules != NULL;
- modules = modules->next)
- {
-
- if (!strcmp(modules->name, ADVMODNAME))
- {
- if (advise_module_pushed)
- continue;
-
- advise_module_pushed = 1;
- }
-
- if (ioctl(0, I_PUSH, modules->name))
- {
- (void) fprintf(stderr, "%s: Couldn't I_PUSH: %s (%s).\n",
- progname, modules->name, strerror(errno));
- error++;
- }
- }
-
- (void) ioctl(0, TCSETS, &termios);
- }
-
- if (!allow_advise && !status)
- {
- (void) ioctl(0, TCGETS, &termios);
-
- modules = list_modules(0, ADVMODNAME);
-
- while (modules != NULL)
- {
- if (strcmp(modules->name, ADVMODNAME))
- {
- if (ioctl(0, I_PUSH, modules->name))
- {
- (void) fprintf(stderr,
- "%s: Couldn't I_PUSH: %s (%s).\n",
- progname, modules->name,
- strerror(errno));
- error++;
- }
- }
-
- modules = modules->next;
- }
-
- (void) ioctl(0, TCSETS, &termios);
- }
-
- if (!allow_deny_p)
- return error ? 1 : 0;
- }
-
- if (allow_deny_p)
- {
- if (ioctl(0, allow_deny, 0))
- {
- if (errno == EINVAL)
- {
- (void) fprintf(stderr, "%s: module \"%s\" not in stream.\n",
- progname, ADVMODNAME);
- }
- else
- {
- (void) fprintf(stderr, "%s: Couldn't set advisory mode (%s).\n",
- progname, strerror(errno));
- }
-
- return 1;
- }
-
- goto advstat;
- }
-
- /* All switches have been handled */
-
- argc -= optind;
- argv += optind;
-
- if (argc > 1)
- {
- usage();
- }
-
- if (argc == 0)
- {
- int retval, status;
-
- advstat:
- /*
- ** Status of advise.
- */
-
- retval = ioctl(0, ADVISE_STATUS, &status);
- #if !defined(M_COPYOUT) && !defined(sun)
- status = !retval;
- #endif /* n M_COPYOUT */
-
- if (retval)
- {
- printf("Module \"%s\" not pushed on stream.\n", ADVMODNAME);
- }
- else
- {
- printf("Advise access %s\n", status ? "allowed" : "denied");
- }
-
- return 0;
- }
-
- advise(*argv);
-
- return 0;
- }
-
- static void
- usage(
- #ifdef __STDC__
- void
- #endif /* __STDC__ */
- )
- {
- (void) fprintf(stderr, "usage: %s [-ADad?] [-M module] | [-Ssr] [-m char] [ device | username ]\n",
- progname);
- exit(1);
- }
-
- struct termios termios, oldtermios;
-
- void restoretermios(sig)
- {
- (void) ioctl(0, TCSETS, &oldtermios);
- exit(0);
- }
-
- static void
- #ifdef __STDC__
- advise(char *who)
- #else
- advise(who)
- char *who;
- #endif /* __STDC__ */
- {
- int ret, fd, metad=0;
- char buf[1024], *device=NULL, *devname, *login_name, *tty_name;
- struct pollfd pfds[2];
- struct stat stbuf;
- struct utmp *ut, uts;
- char username[sizeof(ut->ut_name) + 1];
-
- username[0] = '\0';
-
- if (*who == '/') /* full path name */
- device = who;
- else
- {
- /* Either this is /dev/ + who OR a username */
-
- setutent();
-
- while ((ut = getutent()) != NULL)
- {
- if (
- #ifdef USER_PROCESS
- (ut->ut_type==USER_PROCESS) &&
- #endif /* USER_PROCESS */
- (!strncmp(who, ut->ut_name, sizeof(ut->ut_name))))
- {
- if(device) free(device);
- device = (char *)malloc(sizeof("/dev/") +
- sizeof(ut->ut_line));
-
- if (device == NULL)
- {
- (void) fprintf(stderr,
- "%s: malloc failed (Out of Memory)\n",
- progname);
-
- exit(1);
- }
-
- strcpy(device, "/dev/");
- strncat(device, ut->ut_line, sizeof(ut->ut_line));
- device[sizeof("/dev/")+sizeof(ut->ut_line)] = '\0';
-
- strncpy(username, ut->ut_name, sizeof(ut->ut_name));
- username[sizeof(ut->ut_name)] = '\0';
- if(!strcmp(device, ttyname(0))) continue;
- break;
- }
- }
-
- if (device == NULL) /* Is /dev/ + who */
- {
- device = (char *)malloc(sizeof("/dev/") + strlen(who));
-
- if (device == NULL)
- {
- (void) fprintf(stderr, "%s: malloc failed (Out of Memory)\n",
- progname);
-
- exit(1);
- }
-
- strcpy(device, "/dev/");
- strcat(device, who);
- }
-
- endutent();
- }
-
- devname = device + sizeof("/dev/") - 1;
-
- if (username[0] == '\0')
- {
- setutent();
-
- strncpy(uts.ut_line, devname, sizeof(uts.ut_line));
-
- if ((ut = getutline(&uts)) != NULL)
- {
- strncpy(username, ut->ut_name, sizeof(ut->ut_name));
- username[sizeof(ut->ut_name)] = '\0';
- }
- else
- {
- strcpy(username, "unknown");
- }
-
- endutent();
- }
-
- if(!strcmp(device, ttyname(0)))
- {
- (void) fprintf(stderr, "%s: Can't advise yourself!\n", progname);
- exit(1);
- }
-
- if (stat(device, &stbuf) < 0)
- {
- if (errno == ENOENT)
- {
- if(*who=='/') (void) fprintf(stderr, "%s: no advisee device \"%s\"\n", progname, device);
- else (void) fprintf(stderr, "%s: unknown user \"%s\" or no advisee device \"%s\"\n", progname, who, device);
- }
- else
- {
- (void) fprintf(stderr,
- "%s: Couldn't stat() advisee device: %s (%s)\n",
- progname, device, strerror(errno));
- }
- exit(1);
- }
-
- if ((fd = open("/dev/advise", O_RDWR|O_NONBLOCK)) < 0)
- {
- (void) fprintf(stderr,
- "%s: Couldn't open advisory device: /dev/advise (%s)\n",
- progname, strerror(errno));
- exit(1);
- }
- setuid(getuid());
-
- if (ioctl(fd, reverse?ADVISE_SETADVISEERD:ADVISE_SETADVISEEWR,
- #ifdef sun
- &
- #endif /* sun */
- stbuf.st_rdev))
- {
- if (errno == EUNATCH)
- {
- (void) fprintf(stderr,
- "%s: module \"%s\" not in place for %s\n",
- progname, ADVMODNAME, device);
- } else if (errno == EACCES)
- {
- (void) fprintf(stderr, "%s: Permission denied\n", progname);
- } else
- {
- (void) fprintf(stderr,
- "%s: Couldn't set advisee: %s (%lu, %lu) (%s)\n",
- progname, device,
- #ifdef sun
- major(stbuf.st_rdev), minor(stbuf.st_rdev),
- #else
- ((stbuf.st_rdev >> 16) &0xFFFF), (stbuf.st_rdev&0xFFFF),
- #endif /* sun */
- strerror(errno));
- }
- exit(1);
- }
-
- if (!secret)
- {
- char *str;
- struct passwd *pt;
-
- if ((login_name = getlogin()) == NULL)
- {
- pt = getpwuid(getuid());
-
- if (pt == NULL || pt->pw_name == NULL)
- {
- login_name = "somebody";
- }
- else
- {
- login_name = pt->pw_name;
- }
- }
-
- if ((tty_name = ttyname(2)) != NULL)
- {
- if (!strncmp(tty_name, "/dev/", sizeof("/dev/")-1))
- tty_name += sizeof("/dev/")-1;
- }
- else
- tty_name = "somewhere";
-
- str = malloc(strlen(login_name) + strlen(tty_name) +
- sizeof("[: advising :]\n\r") + strlen(username) +
- strlen(devname));
-
- if (str)
- {
- struct advise_message m;
- struct strbuf ctl, data;
-
- m.type = ADVISE_READDATA;
-
- ctl.len = sizeof(m);
- ctl.buf = (void *)&m;
-
- sprintf(str, "[%s:%s %s %s:%s]\n\r", login_name,
- tty_name, spy ? "spying" : "advising", username, devname);
-
- data.len = strlen(str);
- data.buf = str;
-
- (void) putmsg(fd, &ctl, &data, 0);
-
- free(str);
- }
- }
-
-
- (void) ioctl(0, TCGETS, &termios);
-
- oldtermios = termios;
- signal(SIGTERM, restoretermios);
- termios.c_oflag &= ~OPOST;
-
- if (!spy)
- {
- termios.c_cc[VMIN] = 1;
- termios.c_cc[VTIME] = 0;
- termios.c_lflag &= ~(ISIG|ICANON|ECHO);
- } else signal(SIGINT, restoretermios);
- (void) ioctl(0, TCSETS, &termios);
-
- pfds[0].fd = fd;
- pfds[0].events = POLLIN;
-
- pfds[1].fd = 0;
- pfds[1].events = POLLIN;
-
- for (;;)
- {
- if (poll(pfds, spy?1:2, INFTIM) < 0)
- continue;
-
- if ((pfds[0].revents&POLLHUP) != 0) /* module removed */
- {
- (void) ioctl(0, TCSETS, &oldtermios);
- exit(0);
- }
- if ((pfds[0].revents&POLLIN) != 0) /* data from advisee ready */
- {
- if ((ret = read(fd, buf, sizeof(buf))) > 0)
- write(1, buf, ret);
- }
-
- if (!spy && ((pfds[1].revents&POLLIN) != 0)) /* data from advisor ready */
- {
- if ((ret = read(0, buf, sizeof(buf))) > 0)
- {
- register int i;
- register char *p = buf, *pp=buf;
-
- for (i=0; i < ret; ++i, p++)
- {
- if (metad)
- {
- if (metad == 2)
- {
- meta_character = *p;
- printf("The meta character is now: %s\n",
- strchar(meta_character));
- pp++;
- metad = 0;
- continue;
- }
-
- switch (*p)
- {
- case '=':
- metad=2;
- pp++;
- break;
-
- case '?':
- {
- char *escstr = strchar(meta_character);
-
- printf("Help for meta character <%s>:\n",
- escstr);
- printf("%s?\t-- This help message.\n", escstr);
- printf("%s~\t-- Send a single meta character.\n",
- escstr);
- printf("%s.\t-- Disconnect advise session.\n",
- escstr);
- printf("%s=C\t-- Change meta character to C.\n",
- escstr);
- printf("%s^Z\t-- Suspend advise session.\n",
- escstr);
- pp++;
- metad=0;
- break;
- }
-
- case '.':
- {
- if (!secret)
- {
- char *str;
-
- str = malloc(strlen(login_name) +
- strlen(tty_name) +
- sizeof("[: disconnecting from :]\n") +
- strlen(username) + strlen(devname));
-
- if (str)
- {
- struct advise_message m;
- struct strbuf ctl, data;
-
- m.type = ADVISE_READDATA;
-
- ctl.len = sizeof(m);
- ctl.buf = (void *)&m;
-
- sprintf(str, "[%s:%s disconnecting from %s:%s]\n\r",
- login_name, tty_name, username,
- devname);
-
- data.len = strlen(str);
- data.buf = str;
-
- (void) putmsg(fd, &ctl, &data, 0);
-
- free(str);
- }
- }
-
- close(fd);
-
- (void) ioctl(0, TCSETS, &oldtermios);
-
- exit(0);
- }
-
- case CTRL('Z'):
- {
- (void) ioctl(0, TCSETS, &oldtermios);
- (void) signal(SIGTSTP, SIG_DFL);
- (void) kill(0, SIGTSTP);
- (void) ioctl(0, TCSETS, &termios);
- pp++;
- metad=0;
- break;
- }
-
- default:
- metad=0;
- break;
- }
- }
- else
- {
- if (*p == meta_character)
- {
- int d = p - pp;
-
- metad=1;
-
- if (d) write(fd, pp, d);
-
- pp += d + 1;
- i += d;
- }
- }
- }
-
- if (p - pp) write(fd, pp, p-pp);
- }
- }
- }
- }
-
- static struct module_list *
- #ifdef __STDC__
- list_modules(int fd, char *push_below)
- #else
- list_modules(fd, push_below)
- char *push_below;
- #endif /* __STDC__ */
- {
- char lookbuf[max(FMNAMESZ+1,256)];
- struct module_list *mp, *mpp;
-
- mp = NULL;
-
- while (ioctl(fd, I_LOOK, lookbuf) == 0)
- {
- if (ioctl(fd, I_POP, 0))
- {
- (void) fprintf(stderr, "%s: Couldn't I_POP: %s (%s).\n", progname,
- lookbuf, strerror(errno));
- return mp;
- }
-
- if ((mpp = (struct module_list *)malloc(sizeof(struct module_list)))
- == NULL || (mpp->name = malloc(strlen(lookbuf) + 1)) == NULL)
- {
- (void) fprintf(stderr, "%s: Couldn't malloc (out of memory).\n",
- progname);
- return mp;
- }
-
- mpp->next = mp;
- mp = mpp;
-
- strcpy(mp->name, lookbuf);
-
- if (!strcmp(push_below, lookbuf))
- break;
- }
-
- return mp;
- }
-
- static char *
- #ifdef __STDC__
- strchar(char character)
- #else
- strchar(character)
- char character;
- #endif /* __STDC__ */
- {
- static char retbuf[4];
- char *p = retbuf;
- int capit = 0;
-
- if (!isascii(character))
- {
- *p++ = '~';
- capit = 1;
- character = toascii(character);
- }
-
- if (iscntrl(character))
- {
- *p++ = '^';
- capit = 1;
- character += '@';
- }
-
- if (capit)
- *p++ = toupper(character);
- else
- *p++ = character;
-
- *p = '\0';
-
- return retbuf;
- }
-