home *** CD-ROM | disk | FTP | other *** search
- From: barrett@Daisy.EE.UND.AC.ZA (Alan P. Barrett)
- Newsgroups: alt.sources
- Subject: apb/mje900117 patches to smail 2.5
- Message-ID: <1991Feb19.213232.8300@Daisy.EE.UND.AC.ZA>
- Date: 19 Feb 91 21:32:32 GMT
-
- Archive-name: smail2.5/apbmje900117
-
- apb/mje900117 patches to smail 2.5
- ==================================
-
- Here are some patches for smail version 2.5. The diffs below are
- relative to the original distribution of smail2.5 (patchlevel 00). This
- patch will not change the patchlevel in 'patchlevel.h', because it is
- not an 'official' patch, but it will change the version string in
- defs.h.
-
- Changes marked [apb] are mine (Alan Barrett <barrett@ee.und.ac.za>), and
- changes marked [mje] are originally by Mark Elkins <mje@olsa99.UUCP>. I
- have made minor modifications to his code, including adding #defines in
- defs.h and putting the code inside #ifdef ... #endif where appropriate.
-
-
- How to apply the patch
- ----------------------
-
- (1) If you have a version of the 'patch' program that understands
- unidiff format, just pipe this file into the standard input of a
- command like "patch -l -d /usr/local/src/smail". The '-l' option
- tells patch not to be too fussy about white space (because I have
- been working from sources in which the white space has been munged
- -- sorry). The '-d' option tells it to apply the patch to files in
- the directory whose name appears next. Make sure you use the right
- directory name.
-
- (2) If your patch doesn't like unidiffs, first get Wayne Davison's
- unidiff package from comp.sources.unix volume 14.
-
- (3) If you don't have 'patch', use an editor and lots of patience to
- make all the changes, or get 'patch' first.
-
-
- List of changes
- ---------------
-
- There are a few bug fixes:
-
- (1) The binary search routines were wrong (in two separate places,
- dealing with the paths file and the fullnames file). [apb]
-
- (2) Addresses that contained characters that are special to the shell
- were not treated properly. Now the address is quoted in such a way
- that the shell will never clobber them. (Changed definition of
- LARG and RARG in defs.h, added calls to sh_quote() in several
- places.) [apb]
-
- (3) There are a few more places where the address should be checked for
- "postmaster". [apb]
-
- (4) The stderr file should be opened in append mode, so that stdout and
- stderr don't get garbled in the "standard error follows" section of
- a return-to-sender error message. [apb]
-
- (5) When a line in the paths file starts with a dot then the '%s' has
- to be replaced by 'domain!user', not just by the 'user' name.
- [apb]
-
- There are a few enhancements:
-
- (1) You can define FAILPOSTMASTER (in defs.h) to make the postmaster
- get a copy of all failed mail messages. [apb]
-
- (2) You can define DOT_EOF and DOT_EOF_ALL (in defs.h) to modify
- smail's behaviour when it sees a message that contains a line with
- only a dot on it. The original version treated it like EOF, but
- now you can tell the program to (a) always treat a dot line as EOF,
- (b) treat a dot line as EOF only if input is from a tty, or (c)
- tell the program to never treat a dot line as EOF. [apb]
-
- (3) The arpadate function now returns a string that is legal according
- to a strict interpretation of RFC822. See the comments in the code
- for details. [apb]
-
- (4) "postmast" is now treated exactly like "postmaster". This is for
- compatibility with sites that have 8-character user names. [apb]
-
- (5) Look for a smart-host even if routing is not set to REROUTE. This
- may not have been such a good idea, but I like it and it works
- better now that change number 9 below has also been made. [apb]
-
- (6) If we get a local address with a '%' in it, change the '%' to an
- '@' and try again. [apb]
-
- (7) If a path cannot be found in the usual way, check whether the
- desired domain (or host) name is a truncated version of a known
- domain name. This will find 'abc.def.ghi' in the paths file if it
- is looking for 'abc.def'. Controlled by TRUNC_DOM in defs.h.
- [mje]
-
- (8) If that also didn't work, see whether the leftmost part of the
- desired domain (or host) name matches the leftmost part of any
- domain (or host) name known to the paths file. This will find
- 'abc.something.else' or plain 'abc' in tha paths file if it is
- looking for 'abc.def'. Controlled by TRUNC_DOM_LEFT in defs.h.
- [mje]
-
- (9) If that also didn't work, see if the leftmost part of the desired
- domain (or host) name matches any of the uucp neighbours reported
- by the uuname command. This will find 'abc' in your L.sys or
- Systems file if it is looking for 'abc.def.ghi'. Controlled by
- UUNAME in defs.h. [mje]
-
- (10) Remove all explicit routing through the local system during the
- alias processing stage, and be much more robust about deciding when
- a domain name refers to the local system. Now, paths like
- hostname!hostname.hostdomain!hostname!user will correctly resolve
- to 'user' instead of being treated as erroneous. There are still
- some problems that may show up if routing = REROUTE and the local
- system name appears at the end of a path via other systems. [apb]
-
- (11) Try harder to be sensible about quoted local parts in addresses
- like <"user"@myname>, or even <"user@some.where"@myname.mydom>.
- [apb]
-
- (12) When looking in the paths file for a route to something like
- 'abc.def.ghi,' first try the full name without an initial dot
- ('abc.def.ghi'), before trying with an initial dot
- ('.abc.def.ghi'). Both might appear in the paths file, and we want
- to find the right one first. If that is not found, then continue
- as before, looking for '.def.ghi', 'def.ghi', '.ghi' and 'ghi' in
- that order. [apb]
-
- (13) New RLFROM macro in defs.h allows the "From " line in mail from a
- remote user to a local user to be different from that in mail from
- a remote user to a remote user. Useful because mail sent via uucp
- should have 'remote from thishost' in the From line, but you may
- not want 'remote from otherhost' in the From line of mail delivered
- locally. [apb]
-
- (14) Get real name in the From line even if the person sending the mail
- is su'ed to another user id. [mje]
-
- (15) Make the stderr file unbuffered, to help with debugging. Line
- buffering would also be fine, on systems where it works. [apb]
-
- There are a few gratuitous changes:
-
- (1) The version name (in defs.h).
-
- (2) The LMAIL macro in defs.h calls /usr/local/bin/deliver, which I
- prefer because it doesn't chop messages off when it sees a dot
- line. "deliver" also allows one to do some fancy stuff, but I
- haven't really tried that. [apb]
-
- (3) MAXCLEN in defs.h is much bigger, to allow more addresses to be
- passed with a single copy of a message. Make sure my value isn't
- too big for your system, and remember that smail will actually
- exceed the limit you specify here, so be conservative. [apb]
-
- (5) The text of the return-to-sender message is altered. [apb]
-
- (6) Indentation has been changed in functions that were creeping off
- the right hand side of the page. [apb]
-
-
- ----- start of diffs -----
-
- Index: Makefile
- *** old/Makefile Thu Jan 18 17:03:41 1990
- --- new/Makefile Thu Jan 18 17:04:09 1990
- @@ -8,7 +8,8 @@
- #
- #LIBS = -lmalloc
-
- -OBJECTS = main.o map.o resolve.o deliver.o misc.o alias.o pw.o headers.o getpath.o str.o getopt.o
- +OBJECTS = main.o map.o resolve.o deliver.o misc.o alias.o pw.o \
- + headers.o getpath.o str.o getopt.o uuname.o
-
- all: smail svbinmail lcasep pathproc mkfnames nptx
-
-
- Index: alias.c
- *** old/alias.c Thu Jan 18 17:03:42 1990
- --- new/alias.c Thu Jan 18 17:04:09 1990
- @@ -61,6 +61,7 @@
- static int nargc = 0;
- static char *nargv[MAXARGS];
-
- +char *postmaster();
- void add_horz();
- void load_alias(), strip_comments();
- int recipients();
- @@ -83,10 +84,10 @@
- /*
- ** alias the addresses
- */
- - int i;
- - char domain[SMLBUF], ubuf[SMLBUF], *user;
- - node *addr, addrstk;
- - node *flist, fliststk, *u;
- + int i;
- + char domain[SMLBUF], ubuf[SMLBUF], *user;
- + node *addr, addrstk;
- + node *flist, fliststk, *u;
-
- #ifndef SENDMAIL
- FILE *fp;
- @@ -111,7 +112,8 @@
- ** push all of the addresses onto a stack
- */
- for(i=0; i < *pargc; i++) {
- - push(addr, argv[i]);
- + removelocal (argv[i]);
- + push (addr, argv[i]);
- }
-
- /*
- @@ -166,6 +168,9 @@
- #endif
- user = escape(ubuf);
-
- + /* check for postmaster */
- + user = postmaster(user);
- +
- (void) strcpy(u->string, user); /* local => elide domain */
- #ifndef SENDMAIL
- /*
- @@ -259,20 +264,23 @@
- if (index(user, '.') != NULL)
- #endif
- {
- - static char t_dom[SMLBUF], t_unam[SMLBUF];
- - char *t_user = res_fname(user);
- - if (t_user != NULL) {
- - if(islocal(t_user, t_dom, t_unam) == 0) {
- - /* aliased to non-local address */
- - push(addr, t_user);
- - continue;
- - }
- - if(strcmp(t_unam, user) != 0) {
- - /* aliased to different local address */
- - push(addr, t_unam);
- - continue;
- - }
- + static char t_dom[SMLBUF], t_unam[SMLBUF];
- + char t_userbuf[SMLBUF];
- + char *t_user = res_fname(user);
- + if (t_user != NULL) {
- + (void) strcpy (t_userbuf, t_user);
- + NODEBUGremovelocal (t_userbuf);
- + if(islocal(t_userbuf, t_dom, t_unam) == 0) {
- + /* aliased to non-local address */
- + push(addr, t_userbuf);
- + continue;
- }
- + if(strcmp(t_unam, user) != 0) {
- + /* aliased to different local address */
- + push(addr, t_unam);
- + continue;
- + }
- + }
- }
- #endif
-
- @@ -479,7 +487,10 @@
- */
- if((islocal(b, d, u) == 0)
- || (strcmpic(h->string, u) != 0)) {
- - add_horz(h, b);
- + char temp[SMLBUF];
- + (void) strcpy (temp, b);
- + NODEBUGremovelocal (temp);
- + add_horz (h, temp);
- ret = 1;
- }
- SKIPSPACE(p);
- @@ -534,6 +545,9 @@
- if((p = index(str, ':')) != NULL) {
- *p = CNULL;
- }
- + /* check for postmaster */
- + str = postmaster(str);
- +
- if((new = (node *) malloc(sizeof(node))) != NNULL) {
- if((new->string = malloc((unsigned) strlen(str)+1)) == NULL) {
- free(new);
- @@ -560,6 +574,9 @@
- {
- char *malloc();
- node *new;
- +
- + /* check for postmaster */
- + str = postmaster(str);
-
- if((new = (node *) malloc(sizeof(node))) != NNULL) {
- if((new->string = malloc((unsigned) strlen(str)+1)) == NULL) {
-
- Index: defs.h
- *** old/defs.h Thu Jan 18 17:03:42 1990
- --- new/defs.h Thu Jan 18 17:06:31 1990
- @@ -17,7 +17,7 @@
- */
-
- #ifndef VERSION
- -#define VERSION "smail2.5"
- +#define VERSION "smail2.5+apb/mje900117"
- #endif
-
- /*#define BSD /* if system is a Berkeley system */
- @@ -97,6 +98,59 @@
- #define SMARTHOST "smart-host" /* pathalias alias for relay host */
-
- /*
- +** Define FAILPOSTMASTER as the string "postmaster" if you want a copy of
- +** return-to-sender messages to be sent to the local postmaster. Define
- +** it as an empty string "" if you don't want copies.
- +*/
- +
- +#define FAILPOSTMASTER "postmaster" /* postmaster gets failure messages */
- +/*#define FAILPOSTMASTER "" /* postmaster does not get messages */
- +
- +/*
- +** DOT_EOF should be defined and DOT_EOF_ALL should be undefined if you
- +** want a line containing just a dot to be treated as the end of a
- +** message that is read from a terminal.
- +** Both DOT_EOF and DOT_EOF_ALL should be defined if you always want
- +** a dot line to end the message, even when stdin is not a terminal.
- +** They should both be undefined if you never want a dot line to end
- +** a message (but beware, many local delivery programs will still chop
- +** the message, even if smail doesn't).
- +*/
- +
- +#define DOT_EOF /* do dot lines end messages */
- +/*#define DOT_EOF_ALL /* even if stdin not a tty? */
- +
- +/*
- +** Three symbols that control some extra 'guessing' about routes.
- +**
- +** TRUNC_DOM should be defined if you want to try searching through the
- +** paths file for a route that appears to have been truncated.
- +** For example, if you are looking for a route to 'abc.def'
- +** and no route can be found in the normal way, but there is a
- +** route to 'abc.def.xyz.com' then that route will be used.
- +** (But if there is a route to 'def.xyz.com' it still won't be found.)
- +** Leave the symbol undefined if you don't want this behaviour.
- +**
- +** TRUNC_DOM_LEFT works like TRUNC_DOM, but it checks only the leftmost
- +** part of the domain name. For example, if you are looking for
- +** 'abc.def', TRUNC_DOM_LEFT will allow a route to 'abc' or to
- +** 'abc.anything.else' to be used instead.
- +**
- +** UUNAME should be defined as the name of a program that prints
- +** the names of all uucp neighbours, one per line.
- +** When an address vannot be resolved with the paths file, this is used
- +** to guess whether it is a uucp neighbour. For example, if you are
- +** looking for 'abc.def' but can't resolve it using the paths file, but
- +** 'abc' is known to your system as a uucp neighbour, then that route
- +** will be used.
- +** Leave UUNAME undefined if you don't want to make this test.
- +*/
- +
- +#define TRUNC_DOM /* do truncated search ? */
- +/* #define TRUNC_DOM_LEFT /* also for leftmost part? */
- +#define UUNAME "/usr/bin/uuname" /* uuname program */
- +
- +/*
- ** ALIAS and CASEALIAS are used only if SENDMAIL is NOT defined.
- ** Sites using sendmail have to let sendmail do the aliasing.
- ** LOWERLOGNAME maps all local login names into lower case. This
- @@ -152,6 +206,10 @@
- ** LMAIL is the command to invoke the local mail transfer agent.
- ** LARG is how to insulate metacharacters from LMAIL.
- ** RLARG is LARG with host! on the front - to pass a uux addr to sendmail.
- +** LFROM is the From_ line in mail from a local user, and also in all
- +** mail passed on to sendmail.
- +** RFROM is the From_ line in mail from a remote user to a remote user.
- +** RLFROM is the From_ line in mail from a remote user to a local user.
- ** SENDMAIL selects one of two sets of defines below for either
- ** using sendmail or /bin/lmail.
- */
- @@ -180,9 +239,19 @@
- #define RMAIL(flags,from,sys) "%s -a%s %s - %s!rmail",UUX,from,flags,sys /* */
- /*#define RMAIL(flags,from,sys) "%s %s - %s!rmail",UUX,flags,sys /* */
-
- -#define RARG(user) " '(%s)'",user
- -#define RFROM(frm,now,host) "From %s %.24s remote from %s\n",frm,now,host
- +#define RARG(user) " \\(%s\\)",user
- +#define RFROM(frm,now,host) "From %s %.24s remote from %s\n",frm,now,host
-
- +/*
- +** Choose one of the following definitions of RLFROM, depending on whether
- +** you want the 'remote from' stuff in mail that is delivered locally.
- +** Mail delivered via uux to another system uses RFROM (not RLFROM), and that
- +** probably should contain the 'remote from' stuff.
- +*/
- +
- +#define RLFROM(frm,now,host) "From %s!%s %.24s\n",host,frm,now /* */
- +/*#define RLFROM(frm,now,host) RFROM(frm,now,host) /* */
- +
- #ifdef SENDMAIL
-
- #define HANDLE JUSTUUCP /* see HANDLE definition below */
- @@ -189,8 +258,8 @@
- #define ROUTING JUSTDOMAIN /* see ROUTING definition below */
-
- #define LMAIL(frm,sys) "%s -em -f%s",SENDMAIL,frm
- -#define LARG(user) " '%s'",postmaster(user)
- -#define RLARG(sys,frm) " '%s!%s'",sys,frm
- +#define LARG(user) " %s",postmaster(user)
- +#define RLARG(sys,frm) " %s!%s",sys,frm
- #define LFROM(frm,now,host) "From %s %.24s\n",frm,now
-
- #else
- @@ -201,11 +270,12 @@
- #ifdef BSD
- #define LMAIL(frm,sys) "/bin/mail" /* BSD local delivery agent */
- #else
- -#define LMAIL(frm,sys) "/bin/lmail" /* SV local delivery agent */
- +/*#define LMAIL(frm,sys) "/bin/lmail" /* SV local delivery agent */
- +#define LMAIL(frm,sys) "/usr/local/bin/deliver" /* deliver */
- #endif
-
- -#define LARG(user) " '%s'",postmaster(user)
- -#define RLARG(sys,frm) " '%s!%s'",sys,frm
- +#define LARG(user) " %s",postmaster(user)
- +#define RLARG(sys,frm) " %s!%s",sys,frm
- #define LFROM(frm,now,host) "From %s %.24s\n",frm,now
-
- #endif
- @@ -254,7 +324,7 @@
- ** a small value (like 0).
- */
-
- -#define MAXCLEN 128 /* longest command allowed (approx.)
- +#define MAXCLEN 2048 /* longest command allowed (approx.)
- /* this is to keep other's buffers
- ** from overflowing
- */
-
- Index: deliver.c
- *** old/deliver.c Thu Jan 18 17:03:42 1990
- --- new/deliver.c Thu Jan 18 17:04:10 1990
- @@ -32,6 +32,8 @@
- extern char arpanows[]; /* local time in arpadate format*/
- char stderrfile[20]; /* error file for stderr traping*/
-
- +char *sh_quote(); /* quote string to protect it from the shell */
- +
- /*
- **
- ** deliver(): hand the letter to the proper mail programs.
- @@ -69,6 +71,7 @@
- char scommand[SMLBUF]; /* retry command issued */
- char *command; /* actual command */
- char buf[SMLBUF]; /* copying rest of the letter */
- + char temp[SMLBUF]; /* temp storage */
- enum eform form; /* holds form[i] for speed */
- long size; /* number of bytes of message */
- char *flags; /* flags for uux */
- @@ -106,10 +109,11 @@
- (void) unlink(stderrfile);
- (void) strcpy(stderrfile, "/tmp/stderrXXXXXX");
- (void) mktemp(stderrfile);
- - (void) freopen(stderrfile, "w", stderr);
- + (void) freopen(stderrfile, "a", stderr);
- if(debug != YES) {
- - (void) freopen(stderrfile, "w", stdout);
- + (void) freopen(stderrfile, "a", stdout);
- }
- + (void) setbuf (stderr, _IONBF);
-
- *lend = *rend = *send = '\0';
-
- @@ -145,8 +149,9 @@
- sflag = "";
- }
-
- - (void) sprintf(lcommand, LMAIL(from, hostv[i]));
- - (void) sprintf(rcommand, RMAIL(flags, from, hostv[i]));
- + (void) sprintf(lcommand, LMAIL(sh_quote(temp,from), hostv[i]));
- + (void) sprintf(rcommand, RMAIL(flags,
- + sh_quote(temp,from), hostv[i]));
-
- /*
- ** For each address with the same host name and form, append the user
- @@ -184,14 +189,19 @@
- rend += strlen(rend);
-
- if (form == LOCAL) {
- - (void) sprintf(lend, LARG(userv[j]));
- - (void) sprintf(send, LARG(userv[j]));
- + (void) sprintf(lend,
- + LARG(sh_quote(temp,userv[j])));
- + (void) sprintf(send,
- + LARG(sh_quote(temp,userv[j])));
- } else {
- - (void) sprintf(lend, RLARG(hostv[i], userv[j]));
- - (void) sprintf(send, RLARG(hostv[i], userv[j]));
- + char host[SMLBUF], user[SMLBUF];
- + (void) sh_quote(host, hostv[i]);
- + (void) sh_quote(user, userv[i]);
- + (void) sprintf(lend, RLARG(host,user));
- + (void) sprintf(send, RLARG(host,user));
- }
-
- - (void) sprintf(rend, RARG(userv[j]));
- + (void) sprintf(rend, RARG(sh_quote(temp,userv[j])));
- formv[j] = SENT;
- }
- retry:
- @@ -269,7 +279,14 @@
- ** Output our From_ line.
- */
- if (form == LOCAL) {
- + /*
- + ** Mail to a local user
- + */
- #ifdef SENDMAIL
- + /*
- + ** LFROM will probably be:
- + ** From xxxxx!yyyyy!uuuuu ttttt
- + */
- (void) sprintf(buf, LFROM(from, nows, hostname));
- size += strlen(buf);
- (void) fputs(buf, out);
- @@ -276,13 +293,27 @@
- #else
- char *p;
- if((p=index(from, '!')) == NULL) {
- + /*
- + ** Mail from a local user to a remote user.
- + **
- + ** LFROM will probably be:
- + ** From xxxxx!yyyyy!uuuuu ttttt
- + */
- (void) sprintf(buf,
- LFROM(from, nows, hostname));
- size += strlen(buf);
- (void) fputs(buf, out);
- } else {
- - *p = NULL;
- - (void) sprintf(buf, RFROM(p+1, nows, from));
- + /*
- + ** Mail from a remote user to a remote user.
- + **
- + ** RLFROM will probably be:
- + ** From yyyyy!uuuuu ttttt remote from xxxxx
- + ** or:
- + ** From xxxxx!yyyyy!uuuuu ttttt
- + */
- + *p = '\0';
- + (void) sprintf(buf, RLFROM(p+1, nows, from));
- size += strlen(buf);
- (void) fputs(buf, out);
- *p = '!';
- @@ -289,6 +320,12 @@
- }
- #endif
- } else {
- + /*
- + ** Mail to a remote user.
- + **
- + ** RFROM will probably be:
- + ** From xxxxx!yyyyy!uuuuu ttttt remote from hhhhh
- + */
- (void) sprintf(buf, RFROM(from, nows, hostname));
- size += strlen(buf);
- (void) fputs(buf, out);
- @@ -418,6 +455,7 @@
- {
- char buf[SMLBUF];
- char domain[SMLBUF], user[SMLBUF];
- + char dom[SMLBUF], usr[SMLBUF];
- char *r;
- FILE *fp, *out, *popen();
- int i = 0;
- @@ -428,11 +466,16 @@
- r += strlen(r);
-
- if(islocal(from, domain, user)) {
- - (void) sprintf(r, LARG(user));
- + (void) sprintf(r, LARG(sh_quote(usr,user)));
- } else {
- - (void) sprintf(r, RLARG(domain, user));
- + (void) sh_quote(dom,domain);
- + (void) sh_quote(usr,user);
- + (void) sprintf(r, RLARG(dom, usr));
- }
-
- + r += strlen(r);
- + (void) sprintf (r, " %s", FAILPOSTMASTER);
- +
- i = 0;
- do {
- out = popen(buf, "w");
- @@ -451,11 +494,16 @@
- return;
- }
-
- + (void) fprintf(out, LFROM("postmaster", nows, hostname));
- (void) fprintf(out, "Date: %s\n", arpanows);
- - (void) fprintf(out, "From: MAILER-DAEMON@%s\n", hostdomain);
- - (void) fprintf(out, "Subject: failed mail\n");
- + (void) fprintf(out, "From: Smail Mail Server <Postmaster@%s>\n", hostdomain);
- + (void) fprintf(out, "Subject: Failed mail\n");
- (void) fprintf(out, "To: %s\n", from);
- (void) fprintf(out, "\n");
- + (void) fprintf(out, "\
- +Your message could not be delivered, because the following command returned\n\
- +an error status. Perhaps one or more of the destination addresses is\n\
- +incorrect.\n\n");
- (void) fprintf(out, "======= command failed =======\n\n");
- (void) fprintf(out, " COMMAND: %s\n\n", fcommand);
-
-
- Index: getpath.c
- *** old/getpath.c Thu Jan 18 17:03:43 1990
- --- new/getpath.c Thu Jan 18 17:04:10 1990
- @@ -16,87 +16,104 @@
- **
- */
-
- -getpath( key, path , cost)
- +getpath( key, path , cost, trunk)
- char *key; /* what we are looking for */
- char *path; /* where the path results go */
- int *cost; /* where the cost results go */
- +int trunk; /* Do we accept a truncated name ? */
- {
- - long pos, middle, hi, lo;
- - static long pathlength = 0;
- - register char *s;
- - int c;
- - static FILE *file;
- - int flag;
- + long pos, middle, hi, lo;
- + static long pathlength = 0;
- + register char *s;
- + int c;
- + static FILE *file;
- + int flag;
-
- -DEBUG("getpath: looking for '%s'\n", key);
- +DEBUG("getpath: looking for '%s'%s\n", key, (trunk?" (truncated)":""));
-
- - if(pathlength == 0) { /* open file on first use */
- - if((file = fopen(pathfile, "r")) == NULL) {
- - (void) printf("can't access %s.\n", pathfile);
- - pathlength = -1;
- - } else {
- - (void) fseek(file, 0L, 2); /* find length */
- - pathlength = ftell(file);
- - }
- + if(pathlength == 0) { /* open file on first use */
- + if((file = fopen(pathfile, "r")) == NULL) {
- + (void) printf("can't access %s.\n", pathfile);
- + pathlength = -1;
- + } else {
- + (void) fseek(file, 0L, 2); /* find length */
- + pathlength = ftell(file);
- }
- - if( pathlength == -1 )
- - return( EX_OSFILE );
- + }
- + if( pathlength == -1 )
- + return( EX_OSFILE );
-
- - lo = 0;
- - hi = pathlength;
- - (void) strcpy( path, key );
- - (void) strcat( path, "\t" );
- -/*
- -** "Binary search routines are never written right the first time around."
- -** - Robert G. Sheldon.
- -*/
- - for( ;; ) {
- - pos = middle = ( hi+lo+1 )/2;
- - (void) fseek(file, pos, 0); /* find midpoint */
- - if(pos != 0)
- - while(((c = getc(file)) != EOF) && (c != '\n'))
- - ; /* go to beginning of next line */
- - if(c == EOF) {
- - return(EX_NOHOST);
- + lo = 0;
- + hi = pathlength;
- + (void) strcpy( path, key );
- + (void) strcat( path, "\t" );
- + /*
- + ** "Binary search routines are never written right the first time around."
- + ** - Robert G. Sheldon.
- + */
- + for( ; lo <= hi ; ) {
- + pos = middle = ( hi+lo+1 )/2;
- + (void) fseek(file, pos, 0); /* find midpoint */
- + if(pos != 0)
- + while(((c = getc(file)) != EOF) && (c != '\n'))
- + ; /* go to beginning of next line */
- + if(c == EOF) {
- + flag = 1;
- + }
- + else {
- + for( flag = 0, s = path; flag == 0; s++ ) { /* match??? */
- + if( *s == '\0' ) {
- + goto solved;
- }
- - for( flag = 0, s = path; flag == 0; s++ ) { /* match??? */
- - if( *s == '\0' ) {
- - goto solved;
- - }
- - if((c = getc(file)) == EOF) {
- - return(EX_NOHOST);
- - }
- - flag = lower(c) - lower(*s);
- - }
- - if(lo >= middle) { /* failure? */
- - return(EX_NOHOST);
- + if((c = getc(file)) == EOF) {
- + flag = 1;
- }
- - if((c != EOF) && (flag < 0)) { /* close window */
- - lo = middle;
- - } else {
- - hi = middle - 1;
- - }
- + else {
- + flag = lower(c) - lower(*s);
- + /*
- + ** if trunk is set, and the end of the desired key
- + ** coincides with a dot in the current key,
- + ** then treat this as a match.
- + ** For example, desired="abc.xyz.com" and
- + ** actual="abc.xyz".
- + */
- + if (trunk && *s =='\t' && c == '.') {
- + while(((c = getc(file)) != EOF) && c!='\t');
- + goto solved;
- + }
- + }
- + } /* end for */
- }
- -/*
- -** Now just copy the result.
- -*/
- -solved:
- - while(((c = getc(file)) != EOF) && (c != '\t') && (c != '\n')) {
- - *path++ = c;
- + if(flag < 0) { /* close window */
- + lo = middle + 1;
- + } else {
- + hi = middle - 1;
- }
- - *path = '\0';
- -/*
- -** See if the next field on the line is numeric.
- -** If so, use it as the cost for the route.
- -*/
- - if(c == '\t') {
- - int tcost = -1;
- - while(((c = getc(file)) != EOF) && isdigit(c)) {
- - if(tcost < 0) tcost = 0;
- - tcost *= 10;
- - tcost += c - '0';
- - }
- - if(tcost >= 0) *cost = tcost;
- + }
- + /*
- + ** If we get here, the key was not found.
- + */
- + return(EX_NOHOST);
- + /*
- + ** It was found. Now just copy the result.
- + */
- + solved:
- + while(((c = getc(file)) != EOF) && (c != '\t') && (c != '\n')) {
- + *path++ = c;
- + }
- + *path = '\0';
- + /*
- + ** See if the next field on the line is numeric.
- + ** If so, use it as the cost for the route.
- + */
- + if(c == '\t') {
- + int tcost = -1;
- + while(((c = getc(file)) != EOF) && isdigit(c)) {
- + if(tcost < 0) tcost = 0;
- + tcost *= 10;
- + tcost += c - '0';
- }
- - return (EX_OK);
- + if(tcost >= 0) *cost = tcost;
- + }
- + return (EX_OK);
- }
-
- Index: headers.c
- *** old/headers.c Thu Jan 18 17:03:43 1990
- --- new/headers.c Thu Jan 18 17:04:11 1990
- @@ -45,7 +45,86 @@
- NULL , NULL , 'N'
- };
-
- +/*
- +**
- +** removelocal(): delete local domain name from an address.
- +**
- +** The following rules are applied repeatedly until they all fail.
- +**
- +** @myname:address ==> address
- +** @myname,@elsewhere:address ==> @elsewhere:address
- +** address@myname ==> address
- +** myname!address ==> address
- +** "address" ==> address
- +** address%domain ==> address@domain
- +**
- +** This function modifies the input address in-place.
- +**
- +*/
-
- +void
- +removelocal (address)
- +char *address;
- +{
- +/**
- + repeat forever {{ actually, until a 'terminate' statement }}
- + parse the address to {is-local, localpart, domain}.
- + {{ use the 'islocal' function to do this }}
- + if is-local then
- + {{ there were no '@' or '!' chars in the address, or
- + there were such chars but the system name was
- + recognised as the local system }}
- + select
- + localpart is quoted :
- + address := removequotes( localpart )
- + localpart is not quoted and contains "@" or "!" :
- + address := localpart
- + localpart is not quoted, does not contain "@" or "!",
- + but contains "%" :
- + address := convert-%-to-@ ( localpart )
- + localpart is not quoted and does not contain "@", "!" or "%" :
- + address := localpart
- + return
- + endselect
- + else
- + return
- + endif
- + endrepeat
- +**/
- + char localpart[SMLBUF], domain[SMLBUF], temp[SMLBUF], *p;
- + extern int rfc822_do_unquote();
- +
- + for (;;) {
- +
- + DEBUG("removelocal: checking '%s'\n", address);
- +
- + if (islocal (address, domain, localpart)) {
- + /* check if localpart is quoted */
- + if ( rfc822_do_unquote (temp, localpart) ) {
- + (void) strcpy (address, temp);
- + }
- + /* check if localpart contains '@' or '!' */
- + else if (strpbrk(localpart,"@!")) {
- + (void) strcpy (address, localpart);
- + }
- + /* check if localpart contains "%" */
- + else if (p = rindex(localpart,'%')) {
- + *p = '@';
- + (void) strcpy (address, localpart);
- + }
- + /* else localpart is a truly local address */
- + else {
- + (void) strcpy (address, localpart);
- + break; /* out of the loop */
- + }
- + } else {
- + break; /* out of the loop */
- + }
- + }
- + DEBUG("removelocal: result is '%s'\n", address);
- + return;
- +}
- +
- /*
- **
- ** parse(): parse <address> into <domain, user, form>.
- @@ -221,7 +300,14 @@
- {
- enum eform form, parse();
- extern char hostuucp[];
- + char path[SMLBUF];
- + int cost;
- +#ifdef TRUNC_DOM_LEFT
- + char leftpart[SMLBUF], *p;
- +#endif
-
- + /* DEBUG("islocal: checking '%s'\n", addr); /* */
- +
- /*
- ** parse the address
- */
- @@ -235,9 +321,31 @@
- ||(strcmpic(domain, &MYDOM[0]) == 0) /* user@MYDOM w/ dot */
- ||(strcmpic(domain, &MYDOM[1]) == 0) /* user@MYDOM no dot */
- #endif
- - ||(strcmpic(domain, hostuucp) == 0)) {/* user@hostuucp */
- + ||(strcmpic(domain, hostuucp) == 0)){ /* user@hostuucp */
- return(1);
- }
- +
- + /*
- + ** Check the paths file.
- + */
- + if (NODEBUGgetpath (domain, path, &cost, 0) == EX_OK)
- + return (strcmp (path, "%s") == 0);
- +
- +#ifdef TRUNC_DOM
- + if (NODEBUGgetpath (domain, path, &cost, 1) == EX_OK)
- + return (strcmp (path, "%s") == 0);
- +#endif /* TRUNC_DOM */
- +
- +#ifdef TRUNC_DOM_LEFT
- + (void) strcpy (leftpart, domain);
- + if (p=index(leftpart,'.')) *p = '\0';
- + if (NODEBUGgetpath (leftpart, path, &cost, 1) == EX_OK)
- + return (strcmp (path, "%s") == 0);
- +#endif /* TRUNC_DOM_LEFT */
- +
- + /*
- + ** Still not found. It can't be local.
- + */
- return(0);
- }
-
- @@ -268,6 +376,11 @@
- static char splbuf[SMLBUF];
- char from[SMLBUF], domain[SMLBUF], user[SMLBUF];
- void rline(), scanheaders(), compheaders();
- +#ifdef DOT_EOF
- +#ifndef DOT_EOF_ALL
- + int is_tty = isatty(0); /* is stdin a tty ? */
- +#endif
- +#endif
-
- /*
- ** if the mail has already been spooled by
- @@ -337,13 +450,26 @@
-
- /*
- ** now, copy the rest of the letter into the spool file
- - ** terminate on either EOF or '^.$'
- + ** terminate on EOF.
- + ** We might also terminate on a line that just
- + ** contains a dot, depending on compile time options
- + ** and whether the stdin is a terminal.
- */
-
- while(ieof != NULL) {
- (void) fputs(buf, spoolfp);
- - if((fgets(buf, SMLBUF, stdin) == NULL)
- - || (buf[0] == '.' && buf[1] == '\n')) {
- +#ifndef DOT_EOF
- + if( fgets(buf, SMLBUF, stdin) == NULL )
- +#else
- +#if DOT_EOF_ALL
- + if( (fgets(buf, SMLBUF, stdin) == NULL)
- + || (buf[0] == '.' && buf[1] == '\n') )
- +#else
- + if( (fgets(buf, SMLBUF, stdin) == NULL)
- + || (is_tty && buf[0] == '.' && buf[1] == '\n') )
- +#endif
- +#endif
- + {
- ieof = NULL;
- }
- }
- @@ -461,7 +587,16 @@
-
- if (from[0] == '\0') {
- char *login;
- - if ((login = pwuid(getuid())) == NULL) {
- + char *tmpname;
- + /*
- + ** Get login name with cuserid(), then convert to uid with
- + ** pwuserid(). If cuserid() fails, use getuid().
- + ** When we know the uid, let pwuid() convert it to a name.
- + ** (This seems very complicated.)
- + */
- + if ((login = pwuid(
- + (tmpname=cuserid(NULL)) ? pwuserid(tmpname) : getuid()
- + )) == NULL) {
- (void) strcpy(from, "nobody"); /* bad news */
- } else {
- (void) strcpy(from, login);
- @@ -706,7 +841,7 @@
-
- char *nameptr;
- char name[SMLBUF];
- - char *getenv(), *login;
- + char *getenv(), *login, *tmpname;
- char *pwfnam(), *pwuid();
-
- if (from_addr != NULL) {
- @@ -717,7 +852,9 @@
- name[0] = '\0';
- if((nameptr = getenv("NAME")) != NULL) {
- (void) strcpy(name, nameptr);
- - } else if((login = pwuid(getuid())) != NULL) {
- + } else if((login = pwuid(
- + (tmpname=cuserid(NULL)) ? pwuserid(tmpname) : getuid()
- + )) != NULL) {
- if((nameptr = pwfnam(login)) != NULL) {
- (void) strcpy(name, nameptr);
- }
- @@ -755,14 +892,7 @@
- (void) strcat(bol, hostdomain);
- }
- if(i+1 < argc) {
- -#if 0
- - /*** The following line was there, but ii is definitely wrong.
- - I think it should be changed to what appears after the #else.
- - [A P Barrett, 890503] ***/
- - \main);(bol);
- -#else
- n = strlen(bol);
- -#endif
- if(n > 50) {
- (void) strcat(bol, ",\n\t");
- bol = bol + strlen(bol);
- @@ -774,3 +904,35 @@
- }
- }
- }
- +
- +/*
- +** call getpath with the DEBUG flag turned off
- +*/
- +
- +int NODEBUGgetpath (key, path , cost, trunk)
- +char *key; /* what we are looking for */
- +char *path; /* where the path results go */
- +int *cost; /* where the cost results go */
- +int trunk; /* Do we accept a truncated name ? */
- +{
- + enum edebug tdebug = debug;
- + int retcode;
- + debug = NO;
- + retcode = getpath (key, path, cost, trunk);
- + debug = tdebug;
- + return retcode;
- +}
- +
- +/*
- +** call removelocal with the DEBUG flag turned off
- +*/
- +
- +void NODEBUGremovelocal (address)
- +char *address;
- +{
- + enum edebug tdebug = debug;
- + debug = NO;
- + removelocal (address);
- + debug = tdebug;
- +}
- +
-
- Index: misc.c
- *** old/misc.c Thu Jan 18 17:03:44 1990
- --- new/misc.c Thu Jan 18 17:04:12 1990
- @@ -136,6 +136,17 @@
- ** Some sites are now inserting the timezone into the
- ** local date. This routine should figure out what
- ** the format is and work appropriately.
- +**
- +** Modified by A P Barrett, July 1989:
- +** 1 RFC822 format should have weekday at the beginning, with
- +** a comma between it and the rest of the time, instead of
- +** in parentheses at the end.
- +** 2 If the timezone is not one of the few valid RFC822 timezones,
- +** then use the difference between local and GMT to create a
- +** timezone in US Military single-character format (if
- +** #define TZ_MIL is used), or in ANSI X3.51-1975 format (+hhmm)
- +** (if TZ_MIL is not #define'd). In both cases, put the Unix
- +** timezone in as a comment.
- */
-
- char *
- @@ -150,6 +161,7 @@
- #ifndef BSD
- extern char *tzname[];
- time_t t, time();
- + extern long timezone;
- #else
- /* V7 and 4BSD */
- struct timeb t;
- @@ -176,10 +188,22 @@
-
- /*
- ** Crack the UNIX date line in a singularly unoriginal way.
- + **
- + ** Unix: Mon Sep 16 01:03:52 1979
- + ** RFC822: Mon, 16 Sep 79 01:03:52 PST
- + ** or: Mon, 16 Sep 79 01:03:52 H (PST)
- + ** or: Mon, 16 Sep 79 01:03:52 -0800 (PST)
- */
-
- q = b;
-
- + p = &ud[0]; /* Mon */
- + *q++ = *p++;
- + *q++ = *p++;
- + *q++ = *p++;
- + *q++ = ',';
- + *q++ = ' ';
- +
- p = &ud[8]; /* 16 */
- if (*p == ' ')
- p++;
- @@ -209,36 +233,57 @@
- #else
- p = timezone(t.timezone, localtime(&t.time)->tm_isdst);
- #endif
- - if (p[3] != '\0')
- + /* Only a few timezone names are legal in RFC822 */
- + if (strcmp(p,"UT")==0 ||
- + strcmp(p,"GMT")==0 ||
- + strcmp(p,"EST")==0 ||
- + strcmp(p,"EDT")==0 ||
- + strcmp(p,"CST")==0 ||
- + strcmp(p,"CDT")==0 ||
- + strcmp(p,"MST")==0 ||
- + strcmp(p,"MDT")==0 ||
- + strcmp(p,"PST")==0 ||
- + strcmp(p,"PDT")==0 ||
- + (isalpha(*p) && *(p+1)=='\0'))
- {
- - /* hours from GMT */
- - p += 3;
- - *q++ = *p++;
- - if (p[1] == ':')
- - *q++ = '0';
- - else
- - *q++ = *p++;
- - *q++ = *p++;
- - p++; /* skip ``:'' */
- - *q++ = *p++;
- - *q++ = *p++;
- + *q++ = ' ';
- + do { } while ( *q++ = *p++ ); q--;
- }
- else
- {
- +#ifdef TZ_MIL
- + /* Make a US Military style timezone.
- + * Z=GMT, A=GMT-1, N=GMT+1, etc. (J is unused) */
- + static char mil_tz[] = "YXWVUTSRQPONZABCDEFGHIKLM";
- +#ifndef BSD
- + int hr = (timezone+1800)/3600; /* round to nearest hour */
- +#else
- + int hr = (t.timezone+1800)/3600; /* round to nearest hour */
- +#endif
- *q++ = ' ';
- - *q++ = *p++;
- - *q++ = *p++;
- - *q++ = *p++;
- + *q++ = mil_tz[hr+12];
- +#else (not TZ_MIL)
- + /* Make an ANSI X3.51-1975 timezone. +hhmm */
- +#ifndef BSD
- + int hr = abs(timezone)/3600;
- + int mi = (abs(timezone)/60)%60;
- +#else
- + int hr = abs(t.timezone)/3600;
- + int mi = (abs(t.timezone)/60)%60;
- +#endif
- + *q++ = ' ';
- + *q++ = (timezone<0 ? '+' : '-'); /* yes, really */
- + sprintf (q,"%02.2d%02.2d",hr,mi);
- + q += 4;
- +#endif
- +
- + /* Add the Unix timezone as a comment */
- + *q++ = ' ';
- + *q++ = '(';
- + do { } while ( *q++ = *p++ ); q--;
- + *q++ = ')';
- }
-
- - p = &ud[0]; /* Mon */
- - *q++ = ' ';
- - *q++ = '(';
- - *q++ = *p++;
- - *q++ = *p++;
- - *q++ = *p++;
- - *q++ = ')';
- -
- *q = '\0';
- return (b);
- }
- @@ -249,6 +294,9 @@
- * used to convert all case variants of "postmaster" to all lower
- * case. If the user name passed in is not "postmaster", it is
- * returned unchanged.
- + *
- + * Modified by A P Barrett, July 1989:
- + * Treat "postmast" just like "postmaster"
- */
- char *
- postmaster(user)
- @@ -255,8 +303,9 @@
- char *user;
- {
- static char *pm = "postmaster";
- + static char *pm2 = "postmast";
-
- - if(strcmpic(user, pm) == 0) {
- + if (strcmpic(user, pm) == 0 || strcmpic(user, pm2) == 0) {
- return(pm);
- } else {
- return(user);
- @@ -340,3 +389,231 @@
-
- (void) strcat(strcpy(hostuucp, hostname), ".UUCP");
- }
- +
- +/* rfc822_quote --
- + * quotes a character string according to the RFC-822 standard.
- + * Returns a pointer to the result string.
- + *
- + * fred ==> "fred"
- + * funny'name"thing ==> "funny'name\"thing"
- + * "already quoted" ==> "\"already quoted\""
- + */
- +
- +char *rfc822_quote (result, string)
- +char *result, *string;
- + {
- + char *p = string;
- + char *q = result;
- +
- + /* start with the opening quote mark {"} */
- +
- + *q++ = '"';
- +
- + /* process the string */
- +
- + for ( ; *p != '\0' ; p++ ) {
- + if (*p=='"' || *p=='\\') {
- + /* convert embedded {"} or {\} to {\"} or {\\} */
- + *q++ = '\\';
- + *q++ = *p;
- + }
- + else {
- + *q++ = *p;
- + }
- + }
- +
- + /* add last {"} */
- +
- + *q++ = '"';
- +
- + /* terminate with a nul */
- +
- + *q = '\0';
- +
- + return (result);
- + }
- +
- +/* rfc822_isquoted --
- + * determines whether a string is quoted according to the RFC-822 standard.
- + * Returns 1 for TRUE (yes, the string was quoted) or 0 for FALSE.
- + *
- + * fred ==> FALSE
- + * "fred" ==> TRUE
- + * "funny'name\"thing" ==> TRUE
- + * "partially"quoted ==> FALSE
- + * unmatched"quote ==> FALSE
- + * "\"doubly quoted\"" ==> TRUE
- + */
- +
- +int rfc822_isquoted (string)
- +char *string;
- + {
- + return rfc822_do_unquote (NULL, string);
- + }
- +
- +/* rfc822_unquote --
- + * unquotes a character string according to the RFC-822 standard.
- + * Returns a pointer to the result string.
- + * The result is identical to the input if the input string was not
- + * properly quoted.
- + *
- + * fred ==> fred
- + * "fred" ==> fred
- + * "funny'name\"thing" ==> funny'name"thing
- + * "partially"quoted ==> "partially"quoted
- + * unmatched"quote ==> unmatched"quote
- + * "\"doubly quoted\"" ==> "doubly quoted"
- + */
- +
- +char *rfc822_unquote (result, string)
- +char *result, *string;
- + {
- + (void) rfc822_do_unquote (result, string);
- + return result;
- + }
- +
- +/* rfc822_do_unquote --
- + * does the work for both rfc822_isquoted and rfc822_unquote.
- + * The work is the same in both cases; those functions are simply
- + * wrappers that give a different calling interface to this routine.
- + *
- + * Unquotes the string and stores the result in 'result', unless
- + * result is NULL. Returns a flag saying whether or not tha
- + * input string was quoted.
- + */
- +
- +int rfc822_do_unquote (result, string)
- +char *result, *string;
- + {
- + char *p = string;
- + char *q = result;
- + char ch;
- + int wasquoted;
- + typedef enum { start_s, /* at the start of the string */
- + inquotes_s, /* inside a quoted string */
- + backslash_s, /* seen a backslash inside the quoted string */
- + closequote_s, /* seen a quote mark that might be the close of
- + * the quoted string */
- + endquoted_s, /* seen the end of the quoted string */
- + notquoted_s, /* decided that the string was not quoted */
- + end_s /* finished everything */ }
- + state_t;
- + state_t state;
- + int needch;
- +
- + /* This finite state automaton goes through the input string and creates
- + * the output string if the input was properly quoted. If the input
- + * was not properly quoted, it may give up processing the input before
- + * the end of string is reached, and the output will be undefined.
- + * The variable "wasquoted" is set to 1 if the input string was correctly
- + * quoted (in which case the output string will contain the correctly
- + * un-quoted version of the input); this variable is set to 0 if the
- + * input was not correctly quoted. */
- +
- + for ( state = start_s, needch = 1 ; state != end_s ; ) {
- + if (needch) {
- + ch = *p++;
- + needch = 0;
- + }
- + switch (state) {
- + case start_s:
- + /* if the first character is a quote mark then it might be a
- + * properly quoted string, otherwise it cannot be a properly
- + * quoted string */
- + state = ( ch == '"' ? inquotes_s : notquoted_s );
- + needch = 1;
- + break;
- + case inquotes_s:
- + /* backslash and quote marks are special, but just copy other
- + * chars to the output */
- + switch (ch) {
- + case '\\': state = backslash_s; break;
- + case '"': state = closequote_s; break;
- + default: if(q){ *q++ = ch;}
- + }
- + needch = 1;
- + break;
- + case backslash_s:
- + /* if end of string occurs just after a backslash then string
- + * was not properly quoted. Otherwise output the char that
- + * follows the backslash. */
- + if (ch == '\0') { state = notquoted_s; }
- + else { if(q){ *q++ = ch;} state = inquotes_s; needch = 1; }
- + break;
- + case closequote_s:
- + /* if end of string occurs just after a quote mark then
- + * string was properly quoted, otherwise it was not */
- + if (ch == '\0') { if(q){*q++ = '\0';} state = endquoted_s; }
- + else { state = notquoted_s; }
- + break;
- + case endquoted_s:
- + /* String was quoted and we have finished processing it */
- + wasquoted = 1;
- + state = end_s;
- + break;
- + case notquoted_s:
- + /* String was not quoted and we have finished processing it */
- + wasquoted = 0;
- + state = end_s;
- + break;
- + }
- + }
- +
- + /* if the input string was quoted, all the work has been done already.
- + * otherwise, make the output a copy of the input */
- +
- + if (result && ! wasquoted) {
- + (void) strcpy (result, string);
- + }
- +
- + return (wasquoted);
- + }
- +
- +
- +/* sh_quote --
- + * quotes a character string so that, when /bin/sh interprets the result,
- + * the interpretation will be identical to the original string.
- + * Returns a pointer to the result string.
- + *
- + * fred@somewhere ==> 'fred@somewhere'
- + * "funny'name\"thing"@somewhere
- + * ==> '"funny'"'"'name\"thing"@somewhere
- + */
- +
- +char *sh_quote (result, string)
- +char *result, *string;
- + {
- + char *p = string;
- + char *q = result;
- +
- + /* start with the opening quote mark {'} */
- +
- + *q++ = '\'';
- +
- + /* process the string */
- +
- + for ( ; *p != '\0' ; p++ ) {
- + if (*p == '\'') {
- + /* convert embedded {'} to {'"'"'} */
- + *q++ = '\'';
- + *q++ = '\"';
- + *q++ = '\'';
- + *q++ = '\"';
- + *q++ = '\'';
- + }
- + else {
- + *q++ = *p;
- + }
- + }
- +
- + /* add last {'} */
- +
- + *q++ = '\'';
- +
- + /* terminate with a nul */
- +
- + *q = '\0';
- +
- + return (result);
- + }
- +
-
- Index: pw.c
- *** old/pw.c Thu Jan 18 17:03:45 1990
- --- new/pw.c Thu Jan 18 17:04:13 1990
- @@ -54,6 +54,32 @@
- return(NULL);
- }
-
- +pwuserid(user)
- +char *user;
- +{
- + pwlist *f;
- +
- + /*
- + ** check for previously cached user
- + */
- +
- + for(f=pwhead; f != NULL; f=f->vlink) {
- + if(strcmp(user, f->lname) == 0) {
- + return(f->uid);
- + }
- + }
- + /*
- + ** not found parse the password file
- + */
- +
- + while((f=pwparse()) != PNULL) {
- + if(strcmp(user, f->lname) == 0) {
- + return(f->uid);
- + }
- + }
- + return(0);
- +}
- +
- char *
- pwuid(uid)
- int uid;
- @@ -232,14 +258,16 @@
- if ( *s == '\0' ) {
- goto solved;
- }
- - c = getc( file );
- - flag = lower( c ) - lower( *s );
- + if ((c = getc( file )) == EOF)
- + flag = 1;
- + else
- + flag = lower( c ) - lower( *s );
- }
- - if (lo >= middle) /* failure? */
- + if (lo > hi) /* failure? */
- return(NULL);
-
- - if(c != EOF && flag < 0) /* close window */
- - lo = middle;
- + if (flag < 0) /* close window */
- + lo = middle + 1;
- else
- hi = middle - 1;
- }
-
- Index: resolve.c
- *** old/resolve.c Thu Jan 18 17:03:45 1990
- --- new/resolve.c Thu Jan 18 17:04:13 1990
- @@ -50,6 +50,14 @@
- ** This is a gnarly piece of code, but it does it all. Each section
- ** is documented.
- **
- +** **** Note:
- +** Alias and fullname translation should be done whenever an address
- +** resolves to a local name, but it is not. This is only a problem
- +** if routing = REROUTE and we find the local system name at the end of
- +** a path through other systems; in all other cases the local system
- +** name will have been removed already by the aliasing code before
- +** the main program calls resolve().
- +**
- */
-
- enum eform
- @@ -59,13 +67,15 @@
- char *user; /* the returned user */
- int *cost; /* the returned cost */
- {
- - enum eform form; /* the returned form */
- - enum eform parse(); /* to crack addresses */
- - int parts; /* to ssplit addresses */
- - char *partv[MAXPATH]; /* " " " */
- - char temp[SMLBUF]; /* " " " */
- - int i;
- -
- + enum eform form; /* the returned form */
- + enum eform parse(); /* to crack addresses */
- + int parts; /* to ssplit addresses */
- + char *partv[MAXPATH]; /* " " " */
- + char temp[SMLBUF]; /* " " " */
- + int i;
- + char *p;
- +
- +beginning:
-
- /*
- ** If we set REROUTE and are prepared to deliver UUCP mail, we split the
- @@ -73,32 +83,32 @@
- ** substrings until we succeed. Otherwise, we just resolve the whole thing
- ** once.
- */
- - if ((routing == REROUTE) && (rsvp( UUCP ) == UUCP)) {
- - parts = ssplit( address, '!', partv );
- - } else {
- - parts = 1;
- - partv[0] = address;
- - }
- + if ((routing == REROUTE) && (rsvp( UUCP ) == UUCP)) {
- + parts = ssplit( address, '!', partv );
- + } else {
- + parts = 1;
- + partv[0] = address;
- + }
- /*
- ** This for(i) loop selects successively larger
- ** righthand substrings of the address.
- */
- - for( i = parts - 1; i >= 0; i-- ) {
- + for( i = parts - 1; i >= 0; i-- ) {
- /*
- ** Parse the address.
- */
- - (void) strcpy( temp, partv[i] );
- - form = parse( temp, domain, user );
- + (void) strcpy( temp, partv[i] );
- + form = parse( temp, domain, user );
-
- DEBUG("resolve: parse address '%s' = '%s' @ '%s' (%s)\n",
- - temp,user,domain,sform(form));
- + temp,user,domain,sform(form));
-
- /*
- ** If we are looking at a substring (that's not the entire string)
- ** which parses to a LOCAL address, we skip to the next larger substring.
- */
- - if((i != 0) && (form == LOCAL))
- - continue;
- + if((i != 0) && (form == LOCAL))
- + continue;
- /*
- ** Routing, when required, is the next step.
- ** We route the address if we have a ROUTE form
- @@ -105,69 +115,79 @@
- ** or if we have a UUCP form and we are told to
- ** route ALWAYS or REROUTE (i.e., routing != JUSTDOMAIN)
- */
- - if((rsvp( form ) == ROUTE)
- - ||((rsvp( form ) == UUCP) && (routing != JUSTDOMAIN ))) {
- + if((rsvp( form ) == ROUTE)
- + ||((rsvp( form ) == UUCP) && (routing != JUSTDOMAIN ))) {
-
- - int look_smart = 0;
- + int look_smart = 0;
-
- - if((routing == REROUTE) && (i == 0)) {
- - look_smart = 1; /* last chance */
- - }
- + if( /* (routing == REROUTE) && */ (i == 0)) {
- + look_smart = 1; /* last chance */
- + }
-
- - /* route() puts the new route in 'temp' */
- - if(route(domain,user,look_smart,temp,cost) != EX_OK) {
- - continue; /* If routing fails, try
- - /* next larger substring.
- - /* */
- - }
- + /* route() puts the new route in 'temp' */
- + if(route(domain,user,look_smart,temp,cost) != EX_OK) {
- + continue; /* If routing fails, try
- + /* next larger substring.
- + /* */
- + }
- /*
- ** After routing, reparse the new route into domain and user.
- */
- - form = parse( temp, domain, user );
- + form = parse( temp, domain, user );
-
- DEBUG("resolve: parse route '%s' = '%s' @ '%s' (%s)\n",
- - temp,user,domain,sform(form));
- + temp,user,domain,sform(form));
-
- - } else if((getcost) && (rsvp(form) == UUCP)) {
- - /* get the cost of the route
- - ** even if we're not going route the mail.
- - ** this allows smart decisions about using
- - ** the -r flag to uux when we're not routing.
- - */
- - char junk[SMLBUF];
- - if(route(domain,user,0,junk,cost) != EX_OK) {
- - continue; /* If routing fails, try
- - /* next larger substring.
- - /* */
- - }
- - }
- - break; /* route is resolved */
- +
- + } else if((getcost) && (rsvp(form) == UUCP)) {
- + /* get the cost of the route
- + ** even if we're not going route the mail.
- + ** this allows smart decisions about using
- + ** the -r flag to uux when we're not routing.
- + */
- + char junk[SMLBUF];
- + if(route(domain,user,0,junk,cost) != EX_OK) {
- + continue; /* If routing fails, try
- + /* next larger substring.
- + /* */
- + }
- }
- -/*
- -** For LOCAL mail in non-local format, we rewrite the full address into
- -** <user> and leave <domain> blank.
- -*/
- - if ((rsvp( form ) == LOCAL) && (form != LOCAL )) {
- - build( domain, user, form, temp );
- - (void) strcpy( user, temp );
- - (void) strcpy( domain, "" );
- - form = LOCAL;
- - }
- -/*
- -** If we were supposed to route an address but failed (form == ERROR),
- -** or after routing we are left with an address that still needs to
- -** be routed (rsvp( form ) == ROUTE), complain.
- -*/
- - if ((form == ERROR) || (rsvp( form ) == ROUTE )) {
- - exitstat = EX_NOHOST;
- - ADVISE("resolve failed '%s' = '%s' @ '%s' (%s)\n",
- - address, user, domain, sform(form));
- - form = ERROR;
- - } else {
- - ADVISE("resolve '%s' = '%s' @ '%s' (%s)\n",
- - address, user, domain, sform(form));
- - }
- - return ( form );
- + break; /* route is resolved */
- + }
- + /*
- + ** For LOCAL mail in non-local format, we rewrite the full address into
- + ** <user> and leave <domain> blank.
- + */
- + if ((rsvp( form ) == LOCAL) && (form != LOCAL )) {
- + build( domain, user, form, temp );
- + (void) strcpy( user, temp );
- + (void) strcpy( domain, "" );
- + form = LOCAL;
- + }
- + /*
- + ** If we were supposed to route an address but failed (form == ERROR),
- + ** or after routing we are left with an address that still needs to
- + ** be routed (rsvp( form ) == ROUTE), complain.
- + */
- + if ((form == ERROR) || (rsvp( form ) == ROUTE )) {
- + exitstat = EX_NOHOST;
- + ADVISE("resolve failed '%s' = '%s' @ '%s' (%s)\n",
- + address, user, domain, sform(form));
- + form = ERROR;
- + }
- + /*
- + ** If we have a LOCAL address that contains a % then change the %
- + ** to an @ and start again from the beginning.
- + */
- + else if ((form == LOCAL) && ((p = rindex(user,'%')) != NULL)) {
- + *p = '@';
- + strcpy (address, user);
- + goto beginning;
- + } else {
- + ADVISE("resolve '%s' = '%s' @ '%s' (%s)\n",
- + address, user, domain, sform(form));
- + }
- + return ( form );
- }
-
- /*
- @@ -185,93 +205,173 @@
- char *result; /* output route */
- int *cost; /* cost of output route */
- {
- - int uucpdom = 0;
- - int domains, step; /* to split domain */
- - char *domainv[MAXDOMS]; /* " " " */
- - char temp[SMLBUF], path[SMLBUF];
- + int uucpdom = 0;
- + int dotkey; /* did getpath() find a path for a
- + key that began with a "."? */
- + int domains, step; /* to split domain */
- + char *domainv[MAXDOMS]; /* " " " */
- + char temp[SMLBUF], path[SMLBUF];
- + char leftpart[SMLBUF], *up;
-
- -/*
- -** Fully qualify the domain, and then strip the last (top level domain)
- -** component off, so that we look it up separately.
- -*/
- - temp[0] = '.';
- - (void) strcpy(temp+1, domain );
- + /*
- + ** Fully qualify the domain, and then strip the last (top level domain)
- + ** component off, so that we look it up separately.
- + */
- + temp[0] = '.';
- + (void) strcpy(temp+1, domain );
-
- - domains = ssplit( temp+1, '.', domainv );
- + domains = ssplit( temp+1, '.', domainv );
-
- -/*
- -** check target domain for the local host name and host domain.
- -** if it matches, then skip the lookup in the database.
- -** this prevents mail loops for cases where SMARTHOST is defined
- -** in the routing table, but the local host is not. It also is
- -** a little faster when the local host is the target domain.
- -*/
- - if((strcmpic(domain, hostname) == 0)
- - || (strcmpic(domain, hostdomain) == 0)) {
- - step = 0;
- - *cost = 0;
- - (void) strcpy(path, "%s");
- -DEBUG("route: '%s' is local\n", domain);
- - goto route_complete;
- - }
- + /*
- + ** check target domain for the local host name and host domain.
- + ** if it matches, then skip the lookup in the database.
- + ** this prevents mail loops for cases where SMARTHOST is defined
- + ** in the routing table, but the local host is not. It also is
- + ** a little faster when the local host is the target domain.
- + */
- + if((strcmpic(domain, hostname) == 0)
- + || (strcmpic(domain, hostdomain) == 0)) {
- + step = 0;
- + *cost = 0;
- + (void) strcpy(path, "%s");
- + DEBUG("route: '%s' is local\n", domain);
- + goto route_complete;
- + }
-
- - /* If the domain ends in .UUCP, trim that off. */
- - if((domains > 0) && isuucp(domainv[domains-1])) {
- - domains--;
- - domainv[domains][-1] = '\0';
- - uucpdom = 1;
- - }
- -/*
- -** Try to get the path for successive components of the domain.
- -** Example for osgd.cb.att.uucp:
- -** osgd.cb.att
- -** cb.att
- -** att
- -** uucp ( remember stripping top level? )
- -** SMARTHOST
- -** Returns with error if we find no path.
- -*/
- - for(step = 0; (step < domains); step++) {
- - if((getpath(domainv[step]-1, path, cost) == EX_OK) /* w/ dot */
- - || (getpath(domainv[step] , path, cost) == EX_OK))/* no dot */
- - break;
- - }
- + /* If the domain ends in .UUCP, trim that off. */
- + if((domains > 0) && isuucp(domainv[domains-1])) {
- + domains--;
- + domainv[domains][-1] = '\0';
- + uucpdom = 1;
- + }
- + /*
- + ** Try to get the path for successive components of the domain.
- + ** Example for osgd.cb.att.uucp:
- + ** osgd.cb.att
- + ** cb.att
- + ** att
- + ** uucp ( remember stripping top level? )
- + ** truncated name (in this case, osgd or osgd.cb in the paths file )
- + ** osgd ( using uuname to check the uucp L.sys or Systems file )
- + ** SMARTHOST
- + ** Returns with error if we find no path.
- + */
- + for(step = 0; (step < domains); step++) {
- + /*
- + ** Look in the paths file for a route to whatever portion
- + ** of the domain name interests us right now.
- + ** If we are interested in the entire name (step=0) then
- + ** try a path that doesn't start with a dot before trying
- + ** one that does start with a dot.
- + ** If we are interested in something other than the entire
- + ** domain name, try the dot path first.
- + */
- + if (step == 0) {
- + if ((dotkey=0, /* no dot */
- + getpath(domainv[step] , path, cost, 0) == EX_OK)
- + || (dotkey=1, /* with dot */
- + getpath(domainv[step]-1, path, cost, 0) == EX_OK))
- + break; /* found it */
- + } else {
- + if ((dotkey=1, /* with dot */
- + getpath(domainv[step]-1, path, cost, 0) == EX_OK)
- + || (dotkey=0, /* no dot */
- + getpath(domainv[step] , path, cost, 0) == EX_OK))
- + break; /* found it */
- + }
- + } /* end for */
-
- - if(step == domains) {
- + if(step == domains) {
- /*
- - ** we've looked at each component of the domain without success
- + ** We've looked at each component of the domain without success
- + **
- + ** If domain is a UUCP address, look for a UUCP gateway.
- */
- + if((uucpdom == 0)
- + || (dotkey=1, getpath(".UUCP", path, cost, 0) != EX_OK)) {
- + /*
- + ** The domain not is a UUCP address, or we can't
- + ** find a UUCP gateway.
- + */
- + /* extract the leftmost part of the domain name, for use
- + ** with TRUNC_DOM, UUNAME etc.
- + */
- + strcpy(leftpart,domain);
- + if(up=index(leftpart,'.')) *up='\0';
- +#ifdef TRUNC_DOM
- + /*
- + ** See if the domain we want appears
- + ** as a truncated part of a domain in the paths file.
- + */
- + if(getpath(domain, path, cost, 1) == EX_OK) {
- + dotkey = 0; /* no dot */
- + step = 0; /* pretend we matched on full name */
- + goto route_complete;
- + }
- +#endif /* TRUNC_DOM */
- +#ifdef TRUNC_DOM_LEFT
- + /*
- + ** See if the leftmost part of the domain we want appears
- + ** as the leftmost part of a domain in the paths file.
- + */
- + if(getpath(leftpart, path, cost, 1) == EX_OK) {
- + dotkey = 0; /* no dot */
- + step = 0; /* pretend we matched on full name */
- + goto route_complete;
- + }
- +#endif /* TRUNC_DOM_LEFT */
- +#ifdef UUNAME
- + /*
- + ** See if there is a directly connected UUCP
- + ** system whose name matches the first part of
- + ** the full domain name.
- + */
- + if(look_smart == 1) {
- + DEBUG("route: '%s': look for '%s' uucp neighbour\n",
- + domain,leftpart);
- + if (uuname(leftpart)) {
- + DEBUG("route: '%s' is a uucp neighbour\n",leftpart);
- + strcpy(path,leftpart);
- + strcat(path,"!%s"); /* Create a bang path */
- + *cost = 300; /* Average Cost ? */
- + dotkey = 0; /* no dot */
- + step = 0; /* pretend we matched whole name */
- + goto route_complete;
- + }
- + }
- +#endif /* UUNAME */
- +
- + /*
- + ** If this is our last chance,
- + ** look for a smarter host to deliver the mail.
- + */
- + if((look_smart == 0)
- + || (dotkey=0, getpath(SMARTHOST,path,cost,0) != EX_OK)) {
- /*
- - ** If domain is a UUCP address, look for a UUCP gateway.
- + ** All our efforts have been in vain.
- + ** Tell them the bad news.
- */
- - if((uucpdom == 0) || (getpath(".UUCP", path, cost) != EX_OK)) {
- - /*
- - ** The domain not is a UUCP address, or we can't
- - ** find a UUCP gateway. If this is our last chance,
- - ** look for a smarter host to deliver the mail.
- - */
- - if((look_smart == 0)
- - || (getpath(SMARTHOST, path, cost) != EX_OK)) {
- - /*
- - ** All our efforts have been in vain.
- - ** Tell them the bad news.
- - */
- - DEBUG("route '%s' failed\n", domain);
- - return( EX_NOHOST );
- - }
- - }
- + DEBUG("route '%s' failed\n", domain);
- + return( EX_NOHOST );
- + }
- }
- + } /* end if (step==domains) */
-
- -route_complete:
- + /*
- + ** If we get here, we have a route to use.
- + */
- + route_complete:
-
- -DEBUG("route: '%s' (%s) = '%s' (%d)\n", domain, domainv[step]?domainv[step]:"NULL", path, *cost);
- + DEBUG("route: '%s' (%s) = '%s' (%d)\n", domain,
- + domainv[step]?domainv[step]:"NULL", path, *cost);
-
- -/*
- -** If we matched on the entire domain name, this address is fully resolved,
- -** and we plug <user> into it. If we matched on only part of the domain
- -** name, we plug <domain>!<user> in.
- -*/
- - build(domain, user, (step == 0) ? LOCAL : UUCP, temp);
- - (void) sprintf(result, path, temp);
- - return( EX_OK );
- + /*
- + ** If we matched on the entire domain name, this address is fully
- + ** resolved, and we plug <user> into it. If we matched on only part
- + ** of the domain name, or if the match started fith a ".", we plug
- + ** <domain>!<user> in.
- + */
- + build (domain, user, (step == 0 && dotkey == 0) ? LOCAL : UUCP, temp);
- + (void) sprintf(result, path, temp);
- + return( EX_OK );
- }
-
- Index: uuname.c
- *** old/uuname.c Thu Jan 18 17:04:01 1990
- --- new/uuname.c Thu Jan 18 17:04:14 1990
- ***************
- *** 1 ****
- --- 1,44 ----
- + #include <stdio.h>
- + #include "defs.h"
- +
- + /*
- + ** UUNAME - function takes one argument - the name of a possible valid
- + ** uucp site - thats one hop away (ie from the Systems file). If it finds
- + ** name - it returns '1' (ie TRUE) - otherwise it returns a '0' (False).
- + **
- + ** It runs the command 'uuname' and checks the output for that sitename
- + ** (Your arguement). Why a pipe? - This means that you don't have to have
- + ** special permissions to read your Systems file - and it works happily
- + ** regardless of the type of UUCP you are running. Also - its easier to
- + ** fudge if things change - all you need is a program in /usr/bin/uuname!
- + **
- + ** Author - Mark J Elkins - mje@olsa99.UUCP
- + **
- + ** Modified by A P Barrett to use popen instead of pipe/fork/exec,
- + ** and to use the UUNAME preprocessor symbol to define the program to run.
- + */
- +
- + #ifdef UUNAME
- +
- + uuname(match)
- + char *match;
- + {
- + FILE *fp;
- + char buff[40], *p;
- +
- + if ((fp = popen(UUNAME,"r")) == NULL) {
- + perror("smail: cannot popen uuname");
- + return(0);
- + }
- + while(fgets(buff,36,fp)) {
- + if(p=index(buff,'\n')) *p = '\0';
- + if(strcmp(match,buff) == 0) { /* found */
- + (void) pclose(fp);
- + return(1);
- + }
- + }
- + (void) pclose(fp);
- + return(0);
- + }
- +
- + #endif
-
- ----- end of diffs -----
-