home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Subject: v06i071: m - the more/mail/make/man thing
- Reply-To: tcjones@watdragon.waterloo.edu (speedboat jones)
- Distribution: world
- Organization: U. of Waterloo, Ontario
-
- Posting-number: Volume 6, Issue 71
- Submitted-by: tcjones@watdragon.waterloo.edu (speedboat jones)
- Archive-name: m
-
- [It's easier to shoot such people on sight -- or "unalias m" as your first
- action. I don't use alias abbreviations, since their interpretation is
- always open to question and I have to deal with some 30 systems on a day-
- to-day basis, sharing an alias file with at least two other people. ++bsa]
-
- Here is an extremely silly thing called "m". Isn't frustrating how some
- people alias m for mail, others use m for more, and some even use it
- for man? So that when you type at their terminal when they have their
- backs turned you can never get anything right?
-
- M is a more/mail/make/man thing. You just use m instead of any of those
- four and it attempts to figure out what you meant and execute the
- appropriate thing for you. It usually gets it right and if not, well,
- you can't be hurt too much. And you can always use the real command.
-
- This, of course, does not solve the above problem, so I suggest that
- everyone who uses this program changes their prompt to
- I-Use-M:
- so that the rest of the world will know.
-
- Whatever. Have fun etc. This will need a few changes to work on non-BSD
- systems I think.
-
-
- Here is (sort of) what happens...
-
- You type: m thinks:
- ---------------------------------------------
- unix_command | m more
-
- m mail (if there is recent mail)... ELSE
- make (if there is a Makefile or makefile)... ELSE
- mail
-
- m X more X (if X is an ordinary file.) ELSE...
- mail X (if X is a user name or mail alias). ELSE...
- make X (if X is a makefile target).
- man X.
-
- m A, B... mail A, B...
- m x X man x X (if x is a manual section and X a manpage)
- m -f mail -f
- m -f X mail -f X (if X is an ordinary file).
- m -k X man -k X
-
-
-
-
- Terry Jones
-
- Department Of Computer Science, University Of Waterloo
- Waterloo Ontario Canada N2L 3G1. Phone: 1-519-8884674
- UUCP: ...!watmath!watdragon!tcjones
- CSNET, Internet, CDNnet: tcjones@dragon.waterloo.{cdn,edu}
- BITNET: tcjones@WATER.bitnet
- Canadian domain: tcjones@dragon.uwaterloo.ca
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: m m/Makefile m/README m/m.c m/tags
- # Wrapped by tcjones@watdragon on Wed Mar 15 13:01:48 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test ! -d 'm' ; then
- echo shar: Creating directory \"'m'\"
- mkdir 'm'
- fi
- if test -f 'm/Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'m/Makefile'\"
- else
- echo shar: Extracting \"'m/Makefile'\" \(43 characters\)
- sed "s/^X//" >'m/Makefile' <<'END_OF_FILE'
- CFLAGS = -O
- X
- m: m.o
- X cc $(CFLAGS) -o m m.o
- END_OF_FILE
- if test 43 -ne `wc -c <'m/Makefile'`; then
- echo shar: \"'m/Makefile'\" unpacked with wrong size!
- fi
- # end of 'm/Makefile'
- fi
- if test -f 'm/README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'m/README'\"
- else
- echo shar: Extracting \"'m/README'\" \(1835 characters\)
- sed "s/^X//" >'m/README' <<'END_OF_FILE'
- X
- Here is an extremely silly thing called "m". Isn't frustrating how some people
- alias m for mail, others use m for more, and some even use it for man? So that
- when you type at their terminal when they have their backs turned you can never
- get anything right?
- X
- M is a more/mail/make/man thing. You just use m instead of any of those four
- and it attempts to figure out what you meant and execute the appropriate thing
- for you. It usually gets it right and if not, well, you can't be hurt too much.
- And you can always use the real command.
- X
- This, of course, does not solve the above problem, so I suggest that everyone
- who uses this program changes their prompt to
- I-Use-M:
- so that the rest of the world will know :-)
- X
- Whatever. Have fun etc.
- X
- X
- Here is (sort of) what happens...
- X
- You type: m thinks:
- X---------------------------------------------
- unix_command | m more
- X
- m mail (if there is recent mail)... ELSE
- X make (if there is a Makefile or makefile)... ELSE
- X mail
- X
- m X more X (if X is an ordinary file.) ELSE...
- X mail X (if X is a user name or mail alias). ELSE...
- X make X (if X is a makefile target).
- X man X.
- X
- m A, B... mail A, B...
- m x X man x X (if x is a manual section and X a manpage)
- m -f mail -f
- m -f X mail -f X (if X is an ordinary file).
- m -k X man -k X
- X
- X
- X
- X
- Terry Jones
- X
- X Department Of Computer Science, University Of Waterloo
- X Waterloo Ontario Canada N2L 3G1. Phone: 1-519-8884674
- X UUCP: ...!watmath!watdragon!tcjones
- X CSNET, Internet, CDNnet: tcjones@dragon.waterloo.{cdn,edu}
- X BITNET: tcjones@WATER.bitnet
- X Canadian domain: tcjones@dragon.uwaterloo.ca
- END_OF_FILE
- if test 1835 -ne `wc -c <'m/README'`; then
- echo shar: \"'m/README'\" unpacked with wrong size!
- fi
- # end of 'm/README'
- fi
- if test -f 'm/m.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'m/m.c'\"
- else
- echo shar: Extracting \"'m/m.c'\" \(8315 characters\)
- sed "s/^X//" >'m/m.c' <<'END_OF_FILE'
- X/*
- X * m.c -- man/mail/make/more guesswork.
- X *
- X * Invoke one of the above four by looking at our arguments and deciding
- X * which is the appropriate one. Has limitations but is fun...
- X *
- X * Terry Jones
- X *
- X * -----------------------------------------------------------------------------
- X * Department Of Computer Science, University Of Waterloo
- X * Waterloo Ontario Canada N2L 3G1
- X *
- X * {ihnp4,allegra,decvax,utzoo,utcsri,clyde}!watmath!watdragon!tcjones
- X * tcjones@dragon.waterloo.{cdn,edu} tcjones@WATER.bitnet
- X * tcjones%watdragon@waterloo.csnet
- X * -----------------------------------------------------------------------------
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <sys/time.h>
- X
- X/* Some laziness to make things clearer(?) down below */
- X
- X#define MORE go(more, ARGS)
- X#define MAN go("man", ARGS)
- X#define MAIL go("mail", ARGS)
- X#define MAKE go("make", ARGS)
- X
- X#define BIG 4096
- X
- X/* More laziness. ARGn means "original argument n"
- X * RARGn means "real (non-option) argument n"
- X *
- X * Options are assumed to come first on the command line and to start with '-'
- X *
- X */
- X
- X#define ARGS orig_argv
- X#define ARG0 (*orig_argv)
- X#define ARG1 (*(orig_argv+1))
- X#define RARG0 (*argv)
- X#define RARG1 (*(argv+1))
- X
- X/* Sections of the manual that we can recognize. */
- X#define MANSECTIONS "0123456789cinopt"
- X
- X/* Mail is "new" if less than this number of seconds old. */
- X#define NEW_MAIL 120
- X
- extern char *getenv();
- extern char *index();
- extern FILE *openfile();
- X
- char *myname;
- char *more;
- X
- main(argc, argv)
- int argc;
- char **argv;
- X{
- X /* Save the original argument list and count. */
- X register char **orig_argv = argv;
- X register int orig_argc = argc;
- X
- X myname = *argv;
- X
- X argc--;
- X argv++;
- X
- X /* Skip option arguments. */
- X while (**argv == '-'){
- X argv++;
- X argc--;
- X }
- X
- X if (!(more = getenv("PAGER"))) more = "more";
- X
- X /*
- X * argc now hold the number of non-option arguments, argv points
- X * to the first non-option argument.
- X *
- X * The order in which we do the following tests will make an efficiency
- X * difference - try to do more likely and faster tests first.
- X *
- X */
- X
- X if (argc == 0 && isatty(0) == 0) MORE;
- X if (argc == 0 && recent_mail()) MAIL;
- X if (argc == 0 && makefile()) MAKE;
- X if (argc == 1 && is_ord_file(RARG0)) MORE;
- X if (argc > 0 && hascomma(RARG0, RARG1)) MAIL;
- X if (argc == 0) MAIL;
- X if (argc == 1 && is_userid(RARG0)) MAIL;
- X if (argc == 1 && is_mailalias(RARG0)) MAIL;
- X if (argc == 2 && is_manpage(RARG0, RARG1)) MAN;
- X if (orig_argc == 2 && is_minus('f', ARG1)) MAIL;
- X if (orig_argc == 3 && is_minus('f', ARG1) && is_ord_file(RARG0)) MAIL;
- X if (argc == 1 && is_maketarget(RARG0)) MAKE;
- X if (orig_argc == 3 && is_minus('k', ARG1)) MAN;
- X if (argc == 1 && is_sysmailalias(RARG0)) MAIL;
- X if (argc == 1) MAN;
- X
- X
- X /* Give up. */
- X printf("%s: Couldn't decide what to do!\n", myname);
- X exit(1);
- X}
- X
- go(s, args)
- char *s;
- char **args;
- X{
- X /* Exec the command passed in using s, with all the original arguments. */
- X
- X register char **tmp;
- X *args = s;
- X /*
- X * We could print the new command but it doesn't seem necessary -
- X * the result should make it obvious what we have done.
- X *
- X * tmp = args;
- X * while(**tmp) printf("%s ", *tmp++);
- X * putc('\n', stdout);
- X */
- X
- X execvp(s, args);
- X printf(stderr, "%s: Could not execvp %s\n", myname, s);
- X exit(1);
- X}
- X
- X
- is_ord_file(s)
- char *s;
- X{
- X /* Check to see if "s" is an ordinary file. */
- X /* i.e. not a directory etc. */
- X /* if it is executable and also a maketarget then return 0 & it gets made */
- X
- X struct stat sbuf;
- X
- X if (stat(s, &sbuf) == -1) return 0;
- X if (sbuf.st_mode & S_IFMT != S_IFREG) return 0;
- X if ((sbuf.st_mode & S_IEXEC) && is_maketarget(s)) return 0;
- X return 1;
- X}
- X
- hascomma(s1, s2)
- char *s1;
- char *s2;
- X{
- X /*
- X * Check to see if either s1 or s2 has a comma. This would seem to
- X * imply that the arguments are a comma separated list for mail.
- X *
- X */
- X
- X return index(s1, ',') != NULL || index(s2, ',') != NULL;
- X}
- X
- makefile()
- X{
- X /* Check to see if there is a makefile of some description. */
- X
- X struct stat sbuf;
- X return stat("Makefile", &sbuf) == 0 || stat("makefile", &sbuf) == 0;
- X}
- X
- is_minus(flag, s)
- char flag;
- char *s;
- X{
- X /*
- X * Check if "s" is the option given by the flag "flag".
- X * This could be a #define, and so could lots of the next few things.
- X *
- X * But they're ugly.
- X *
- X */
- X
- X return s[0] == '-' && s[1] == flag && s[2] =='\0';
- X}
- X
- X
- is_userid(s)
- char *s;
- X{
- X /*
- X * Is "s" a userid?
- X * Look for a '@' or a '!' for a remote person, or
- X * check /u/"s" to find out locally.
- X *
- X */
- X
- X struct passwd *getpwnam();
- X
- X if (index(s, '!') || index(s, '@')) return 1;
- X return getpwnam(s) != NULL;
- X}
- X
- recent_mail()
- X{
- X /*
- X * See if there is mail which has arrived in the last NEW_MAIL seconds.
- X * This could be much better. It could include a check to see if the
- X * mailbox was touched before you logged on and after your previous
- X * logoff - but who wants to read backwards through /usr/adm/wtmp ??
- X *
- X */
- X
- X char mail[BIG];
- X struct stat sbuf;
- X struct timeval tv;
- X
- X sprintf(mail, "/usr/spool/mail/%s", getenv("USER"));
- X if (stat(mail, &sbuf) == -1) return 0;
- X
- X if (sbuf.st_size == 0) return 0;
- X
- X if (gettimeofday(&tv, NULL) == -1){
- X fprintf(stderr, "Could not gettimeofday\n");
- X exit(1);
- X }
- X
- X return tv.tv_sec - sbuf.st_mtime <= NEW_MAIL;
- X}
- X
- X
- is_manpage(sect, command)
- char *sect;
- char *command;
- X{
- X /* Check to see if there is a man page for "command" in section "sect" */
- X
- X char file[BIG];
- X struct stat sbuf;
- X
- X /* Watch here, there could be sections like 3x or 3f etc etc. */
- X if (strlen(sect) == 1 && index(MANSECTIONS, *sect) == NULL) return 0;
- X
- X sprintf(file, "/usr/man/man%s/%s.%s", sect, command, sect);
- X return stat(file, &sbuf) == 0;
- X}
- X
- X
- is_mailalias(s)
- char *s;
- X{
- X /* Check ~/.mailrc to see if there is an alias by the name of "s" */
- X
- X FILE *f;
- X char line[BIG];
- X int slen = strlen(s);
- X
- X sprintf(line, "/u/%s/.mailrc", getenv("USER"));
- X if ((f = openfile(line, "r", 0)) == NULL) return 0;
- X
- X while (fgets(line, BIG, f) != NULL){
- X register char *temp;
- X
- X if (strncmp(line, "alias", 5)) continue;
- X
- X temp = line + 5;
- X while (*temp == ' ' || *temp == '\t') temp++;
- X
- X if (strncmp(temp, s, slen) == 0) return 1;
- X }
- X return 0;
- X}
- X
- is_sysmailalias(s)
- char *s;
- X{
- X /* Is "s" an alias in /usr/lib/aliases? */
- X
- X FILE *f;
- X char line[BIG];
- X int slen = strlen(s);
- X
- X if ((f = openfile("/usr/lib/aliases", "r", 0)) == NULL) return 0;
- X
- X while (fgets(line, BIG, f) != NULL){
- X if (strncmp(line, s, slen) == 0 && line[slen] == ':') return 1;
- X }
- X return 0;
- X}
- X
- X
- is_maketarget(s)
- char *s;
- X{
- X /* Is "s" a target in a makefile? */
- X
- X FILE *f;
- X char line[BIG];
- X int slen = strlen(s);
- X
- X if ((f = openfile("Makefile", "r", 0)) == NULL)
- X if ((f = openfile("makefile", "r", 0)) == NULL)
- X return 0;
- X
- X while (fgets(line, BIG, f) != NULL){
- X if (strncmp(line, s, slen) == 0 &&
- X (line[slen] == ':' || line[slen] == '\t' || line[slen] == ' '))
- X
- X return 1;
- X }
- X return 0;
- X}
- X
- X
- X#define CLOBBER 1
- X
- XFILE *
- openfile(s,mode,flag)
- char *s;
- char *mode;
- int flag;
- X{
- X /*
- X * fopen() the file whose name is "s".
- X * If mode is write and clobber is 0, don't cloober an existing file.
- X *
- X * flag is clobber mode for "w". 1 = clobber existing file.
- X *
- X */
- X
- X
- X FILE *fp, *fopen();
- X struct stat buf;
- X
- X if (*mode=='w' && flag != CLOBBER && stat(s, &buf) != -1) return NULL;
- X if (!(fp=fopen(s,mode))) return NULL;
- X return fp;
- X}
- END_OF_FILE
- if test 8315 -ne `wc -c <'m/m.c'`; then
- echo shar: \"'m/m.c'\" unpacked with wrong size!
- fi
- # end of 'm/m.c'
- fi
- if test -f 'm/tags' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'m/tags'\"
- else
- echo shar: Extracting \"'m/tags'\" \(451 characters\)
- sed "s/^X//" >'m/tags' <<'END_OF_FILE'
- Mm m.c /^main(argc, argv)$/
- go m.c /^go(s, args)$/
- hascomma m.c /^hascomma(s1, s2)$/
- is_mailalias m.c /^is_mailalias(s)$/
- is_maketarget m.c /^is_maketarget(s)$/
- is_manpage m.c /^is_manpage(sect, command)$/
- is_minus m.c /^is_minus(flag, s)$/
- is_ord_file m.c /^is_ord_file(s)$/
- is_sysmailalias m.c /^is_sysmailalias(s)$/
- is_userid m.c /^is_userid(s)$/
- makefile m.c /^makefile()$/
- openfile m.c /^openfile(s,mode,flag)$/
- recent_mail m.c /^recent_mail()$/
- END_OF_FILE
- if test 451 -ne `wc -c <'m/tags'`; then
- echo shar: \"'m/tags'\" unpacked with wrong size!
- fi
- # end of 'm/tags'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-