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?