[comp.sources.misc] C version of uuque program

allbery@ncoast.UUCP (09/29/87)

[Boy, did this thing bounce around to get to me!  ++bsa]

I rewrote uuque.sh in C so it would be faster.
It needs getopt.

I am leaving the net on Sept 16 but hope to be able to pick up
my mail from this site at a later date.

- - ----------------------------------------------------------
# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# Makefile uuque.c

echo x - Makefile
cat > "Makefile" << '//E*O*F Makefile//'
uuque: uuque.c
	cc -gx uuque.c -lgetopt -o uuque
lint:
	lint uuque.c

install: uuque
	cp uuque /usr/local/bin/uuque
	chown uucp /usr/local/bin/uuque
	chmod u+s /usr/local/bin/uuque

clean:
	-rm -f *.o core uuque

shar:
	shar Makefile uuque.c
//E*O*F Makefile//

echo x - uuque.c
cat > "uuque.c" << '//E*O*F uuque.c//'
/*
 * The user must have access to the /usr/spool/uucp/* directories and files.
 * This can be easily done by making certain users members of the daemon
 * and/or uucp groups.  I have it suid uucp, this does allow everyone to
 * see titles of everyone's mail as it sits in uucp queues which I don't
 * think is too great a violation of privacy.  You could disable the verbose
 * flag for nonprivileged users, or not let them run this at all.
 *
 * Original from turtlevax!ken, C code from pluto!warren, I didn't do much
 * more than recode it into C.  All I added was recognition of poll files
 * in the C. directory and teach it not to complain about a few flags that
 * show up in D.systemX and X. files.
 *
 * It only works on Berkeley UUCP.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>

int verbose;          /* print verbose messages if set */
char *sys;            /* if set, restrict listings to this system */
char our_name[20];        /* local system name */
char dtemplate[20];        /* holds template for data file */
char xtemplate[20];        /* holds template for execute file */

char *strcpy();

main(argc, argv)
char **argv;
{
  init();
  parse_args(argc, argv);

  outgoing();
  incoming();
}

/*
 * Get our own name by executing "uuname -l", use it to make
 * templates for D and X files, and connect to UUCP work directory.
 */

init() {
  FILE *fp, *popen();

  fp = popen("uuname -l", "r");
  (void) fgets(our_name, sizeof our_name, fp);
  (void) pclose(fp);
  strip_newline(our_name);

  (void) sprintf(dtemplate, "D.%s", our_name);
  (void) sprintf(xtemplate, "D.%sX", our_name);

  (void) chdir("/usr/spool/uucp");
}

char *optarg;

parse_args(argc, argv)
char **argv;
{
  int c;

  while ( (c = getopt(argc, argv, "s:v")) > 0)
    switch (c) {
    case 'v':
      verbose = 1; break;
    case 's':
      sys = optarg; break;
    default:
      usage();
    }
}

usage() {
  die("Usage: uuque [-v] [-s system]");
}

die(s)
char *s;
{
  fprintf(stderr, "%s\n", s);
  exit(1);
}

outgoing() {
  DIR *dirp;
  struct direct *dp;
  FILE *fp;
  char othersys[10], job[5];
  char cmdline[256], cmd[256], arg1[256], arg2[256], arg3[256];
  char temp[50], xfile[50], dfile[50], fullxfile[50], from[50];
#define cmdfile dp->d_name

  if ( (dirp = opendir("C.")) == NULL)
    die("cannot open C. directory");

  while ( (dp = readdir(dirp)) != NULL) {
    if ( !parse_filename(dp, othersys, job))
      continue;

    /*
     * if job number is POLL, it's not a real job, just print
     * poll message
     */
    if (strcmp(job, "POLL") == 0) {
      printf("POLL\t%s\n", othersys);
      continue;
    }

    if ( (fp = fopen(sprintf(temp, "C./%s", cmdfile), "r")) == NULL) {
      fprintf(stderr, "cannot open %s\n", cmdfile);
      continue;
    }

    *xfile = *dfile = '\0';
    while (fgets(cmdline, sizeof cmdline, fp)) {
      (void) sscanf(cmdline, "%s %s %s %s", cmd, arg1, arg2, arg3);
      strip_newline(cmdline);

      switch (*cmd) {
        case 'S':      /* uucp send */
        
        if (substring(arg1, xtemplate))
          (void) strcpy(xfile, arg1); /* remote execute file */
        else if (substring(arg1, dtemplate))
          /* data file */
          (void) sprintf(dfile, "D.%s/%s", our_name, arg1);
        else
          /* Just a uucp -- no intertpretation */
          printf("%d\tuucp %s %s!%s (%s)\n",
             file_size(arg1), arg1, othersys, arg2, arg3);

        break;

        case 'R':      /* uucp receive */
        printf("\tuucp %s!%s %s (%s)\n",
             othersys, arg1, arg2, arg3);
        break;

        default:
        printf("Bad command in %s: %s\n", cmdfile, cmdline);
      }
    }
    (void) fclose(fp);

    if (*xfile == '\0')  /* uucp transfer or error */
      continue;

    (void) sprintf(fullxfile, "D.%sX/%s", our_name, xfile);
    if ( (fp = fopen(fullxfile, "r")) == NULL) {
      fprintf(stderr, "cannot open %s\n", xfile);
      continue;
    }

    while (fgets(cmdline, sizeof cmdline, fp)) {
      (void) sscanf(cmdline, "%s %s %s", cmd, arg1, arg2);
      strip_newline(cmdline);

      switch (*cmd) {
        case 'U':
        (void) sprintf(from, "%s!%s", arg2, arg1);
        break;
        case 'F': case 'I': case 'Z': case 'N':
        break;
        case 'C':
        if (strcmp(arg1, "rmail") == 0) {
          FILE *fp1 = fopen(dfile, "r");

          (void) fgets(cmdline, sizeof cmdline, fp1);
          (void) sscanf(cmdline, "%s %s", temp, from);
          printf("%d\t%s %s!%s (%s)\n",
               file_size(dfile), arg1, othersys, arg2, from);
          if (verbose)
            grep("Subject:", fp1);
          (void) fclose(fp1);
        } else if (strcmp(arg1, "rnews") == 0) {
          FILE *fp1 = fopen(dfile, "r");

          printf("%d\t%s %s (%s)\n",
               file_size(dfile), arg1, othersys, from);
          if (verbose) {
            grep("Newsgroups:", fp1);
            grep("Subject:", fp1);
          }
          (void) fclose(fp1);
        } else
          printf("%d\t%s [%s %s] (%s)\n", file_size(dfile),
             cmdline, othersys, dfile, from);
        break;
        default:
        printf("Unknown cmd in %s: %s\n", xfile, cmdline);
      }
    }
    (void) fclose(fp);
  }
  closedir(dirp);
}

incoming() {
  DIR *dirp;
  struct direct *dp;
  FILE *fp;
  char othersys[10], job[5];
  char cmdline[256], cmd[256], arg1[256], arg2[256];
  char temp[50], dfile[50], from[50], *comment;

  if ( (dirp = opendir("X.")) == NULL)
    die("cannot open X. directory");

  while ( (dp = readdir(dirp)) != NULL) {
    if ( !parse_filename(dp, othersys, job))
      continue;

    if ( (fp = fopen(sprintf(temp, "X./%s", cmdfile), "r")) == NULL) {
      fprintf(stderr, "cannot open %s\n", cmdfile);
      continue;
    }

    while (fgets(cmdline, sizeof cmdline, fp)) {
      (void) sscanf(cmdline, "%s %s %s", cmd, arg1, arg2);
      strip_newline(cmdline);

      switch (*cmd) {
        case 'U':
        (void) sprintf(from, "%s!%s", arg2, arg1);
        break;
        case 'Z': case 'N': case 'R': case 'I':
        break;
        case 'F':
        comment = "";
        if (test(sprintf(dfile, "D./%s", arg1)))
          ;
        else if (test(sprintf(dfile, "D.%s/%s", our_name, arg1)))
          ;
        else if (test(sprintf(dfile, "XTMP/%s", arg2)))
          comment = "[EXECUTING]";
        else
          *dfile = '\0'; /* should cause us to give up */
        break;

        case 'C':
        if (strcmp(arg1, "rmail") == 0) {
          FILE *fp1 = fopen(dfile, "r");

          (void) fgets(cmdline, sizeof cmdline, fp1);
          strip_newline(cmdline);
          (void) sscanf(cmdline, "%s %s", arg1, from);
          printf("%d\t%s %s (%s)\n",
               file_size(dfile), cmdline, comment, from);
          if (verbose)
            grep("^Subject:", fp1);
          (void) fclose(fp1);
        } else
          printf("%d\t%s %s (%s)\n", file_size(dfile),
             cmdline, comment, from);
        break;
        default:
        printf("Bad cmd in %s: %s\n", cmdfile, cmdline);
        break;
      }
    }
    (void) fclose(fp);
  }
  closedir(dirp);
}

/*
 * Return true if s2 is a substring of s1.
 */

substring(s1, s2)
char *s1, *s2;
{
  return strcmpn(s1, s2, strlen(s2)) == 0;
}

grep(pattern, fp)
char *pattern;
FILE *fp;
{
  char line[256];

  rewind(fp);
  while (fgets(line, sizeof line, fp))
    if (substring(line, pattern)) {
      printf("\t%s", line);  /* already has a newline at end */
      break;
    }
}

test(file)
char *file;
{
  struct stat st;

  return stat(file, &st) >= 0;
}

file_size(file)
char *file;
{
  struct stat st;

  return stat(file, &st) >= 0 ? st.st_size : 0;
}

/*
 * Format of file is [CX].<system>gnnnn,
 * parse into othersys, grade and job
 *
 * Return zero if name is bad, or if it doesn't match the
 * system we are restricting attention to.
 */

parse_filename(dp, othersys, job)
struct direct *dp;
char *othersys, *job;
{
  if (dp->d_namlen <= 7)
    return 0;

  (void) strcpy(othersys, cmdfile + 2);
  othersys[dp->d_namlen - 7] = '\0';
  (void) strcpy(job, cmdfile + dp->d_namlen - 4);

  /*
   * If sys is set, skip commands for other systems.
   */
   return !sys || strcmp(othersys, sys) == 0;
}

strip_newline(s)
char *s;
{
  int len = strlen(s) - 1;

  if (s[len] == '\n')
    s[len] = '\0';
}
//E*O*F uuque.c//

exit 0
- - -- 
/|/~\~~\    The entire world             Warren Burstein
 |__/__/_/  is a very strange carrot.
 |          But the farmer               philabs!tg!pluto!warren
/           is not afraid at all.        Why doesn't life come with subtitles?