/* * report a recipient to remote */ char * rcptto(char *to) { String *s; s = unescapespecial(bangtoat(to)); if(toline == 0) toline = s_new(); else s_append(toline, ", "); s_append(toline, s_to_c(s)); if(strchr(s_to_c(s), '@')) dBprint("RCPT TO:<%s>\r\n", s_to_c(s)); else { s_append(toline, "@"); s_append(toline, ddomain); dBprint("RCPT TO:<%s@%s>\r\n", s_to_c(s), ddomain); } alarm(10*alarmscale); switch(getreply()){ case 2: break; case 5: return Giveup; default: return Retry; } return 0; }
int ztns_append_bool (ztns_t *self, bool data) { if (data) return s_append (self, "true", '!'); return s_append (self, "false", '!'); }
FUNCTION COUNT t_highlight ( TEXT string[] /* in/out: string to highlight */ ) { TEXT local[STRINGSIZ+1]; /* * t_highlight has a conceptual problem in unix: the escape * sequences in the termcap file have numeric prefixes indicating * the number of milliseconds delay required for highlighting. * Such delays are normally interpreted by tputs, for example * see t_clear. With the TAE highlight concept--i.e., surrounding * a string with escape sequence and letting the user * subsequently write the string with t_write/t_output--we * never have the opportunity to call tputs to interpret the * delays. * * Our approach is to strip the highlighting escape * sequence of this delay element during the initialization * phase. See t_init() above. */ if (stand_out1 == NULL || stand_out2 == NULL) return(0); s_copy (string, local); /* local copy */ s_copy(stand_out1, string); s_append(local, string); s_append(stand_out2, string); return (s_length(stand_out1) + s_length(stand_out2)); }
FUNCTION VOID synerr ( FAST struct SYNBLK *sb, /* in/out: syntax block */ FAST TEXT *es /* in: error message string */ #define NERRCH 10 /* dump 10 chars of surrounding text */ ) { FAST COUNT i; TEXT txt[NERRCH+1]; /* buffer to hold surrounding text */ for (i=0; *es != 0; es++, i++) /* copy caller's string */ { if (i == EMSIZ - (NERRCH+sizeof(" at or near ")+2) ) break; /* don't wipe out */ (*sb).errmsg[i] = *es; /* move caller's string to block */ } s_copy(" at or near ", &(*sb).errmsg[i]); errstr(sb, NERRCH, txt); /* get text surrounding error */ s_append("'", (*sb).errmsg); /* enclose in tick marks */ s_append(txt, (*sb).errmsg); /* append text to EM */ s_append("'", (*sb).errmsg); return; }
void file_path_build( t_file *file) { int c = 0; char path[_PATH_]; bzero( path, _PATH_); if( file->path_type == PATH_RELATIVE) { path[0] = '.'; c++; } else if( file->path_type == PATH_ABSOLUTE) { path[0] = '/'; c++; } int i; for( i = 0; i <= file->dir_count; i++) { c = s_append( path, file->dirs[i], c); c = s_append( path, "/", c); } s_cp( file->path, path, _PATH_); }
/* * if name is int32_ter than Namsiz bytes, try to split it at a slash and fit the * pieces into hp->prefix and hp->name. */ static int putfullname(Hdr *hp, char *name) { int namlen, pfxlen; char *sl, *osl; String *slname = nil; if (isdir(hp)) { slname = s_new(); s_append(slname, name); s_append(slname, "/"); /* posix requires this */ name = s_to_c(slname); } namlen = strlen(name); if (namlen <= Namsiz) { strncpy(hp->name, name, Namsiz); hp->prefix[0] = '\0'; /* ustar paranoia */ return 0; } if (!posix || namlen > Maxname) { fprint(2, "%s: name too int32_t for tar header: %s\n", argv0, name); return -1; } /* * try various splits until one results in pieces that fit into the * appropriate fields of the header. look for slashes from right * to left, in the hopes of putting the largest part of the name into * hp->prefix, which is larger than hp->name. */ sl = strrchr(name, '/'); while (sl != nil) { pfxlen = sl - name; if (pfxlen <= sizeof hp->prefix && namlen-1 - pfxlen <= Namsiz) break; osl = sl; *osl = '\0'; sl = strrchr(name, '/'); *osl = '/'; } if (sl == nil) { fprint(2, "%s: name can't be split to fit tar header: %s\n", argv0, name); return -1; } *sl = '\0'; strncpy(hp->prefix, name, sizeof hp->prefix); *sl++ = '/'; strncpy(hp->name, sl, sizeof hp->name); if (slname) s_free(slname); return 0; }
/* dispose of local addresses */ int cat_mail(dest *dp, message *mp) { Biobuf *fp; char *rcvr, *cp; Mlock *l; String *tmp, *s; int i, n; s = unescapespecial(s_clone(dp->repl1)); if (nflg) { if(!xflg) print("cat >> %s\n", s_to_c(s)); else print("%s\n", s_to_c(dp->addr)); s_free(s); return 0; } for(i = 0;; i++){ l = syslock(s_to_c(s)); if(l == 0) return refuse(dp, mp, "can't lock mail file", 0, 0); fp = sysopen(s_to_c(s), "al", MBOXMODE); if(fp) break; tmp = s_append(0, s_to_c(s)); s_append(tmp, ".tmp"); fp = sysopen(s_to_c(tmp), "al", MBOXMODE); if(fp){ syslog(0, "mail", "error: used %s", s_to_c(tmp)); s_free(tmp); break; } s_free(tmp); sysunlock(l); if(i >= 5) return refuse(dp, mp, "mail file cannot be opened", 0, 0); sleep(1000); } s_free(s); n = m_print(mp, fp, (char *)0, 1); if (Bprint(fp, "\n") < 0 || Bflush(fp) < 0 || n < 0){ sysclose(fp); sysunlock(l); return refuse(dp, mp, "error writing mail file", 0, 0); } sysclose(fp); sysunlock(l); rcvr = s_to_c(dp->addr); if(cp = strrchr(rcvr, '!')) rcvr = cp+1; logdelivery(dp, rcvr, mp); return 0; }
/* * walk up the tree building a Unix style path */ static void unixpath(Node *node, String *path) { if(node == node->parent){ s_append(path, s_to_c(remrootpath)); return; } unixpath(node->parent, path); if(s_len(path) > 0 && strcmp(s_to_c(path), "/") != 0) s_append(path, "/"); s_append(path, s_to_c(node->remname)); }
/* * walk up the tree building a MVS style path */ static void mvspath(Node *node, String *path) { if(node == node->parent){ s_append(path, s_to_c(remrootpath)); return; } mvspath(node->parent, path); if(s_len(path) > 0) s_append(path, "."); s_append(path, s_to_c(node->remname)); }
/* * simplify an address, reduce to a domain */ static String* simplify(char *addr) { int dots, dotlim; char *p, *at; String *s; mklower(addr); at = strchr(addr, '@'); if(at == nil){ /* local address, make it an exact match */ s = s_copy("="); s_append(s, addr); return s; } /* copy up to, and including, the '@' sign */ at++; s = s_copy("~"); for(p = addr; p < at; p++){ if(strchr(".*+?(|)\\[]^$", *p)) s_putc(s, '\\'); s_putc(s, *p); } /* * just any address matching the two most significant domain elements, * except for .uk, which needs three. */ s_append(s, "(.*\\.)?"); p = addr+strlen(addr); /* point at NUL */ if (p[-1] == '.') *--p = '\0'; if (p - addr > 3 && strcmp(".uk", p - 3) == 0) dotlim = 3; else dotlim = 2; dots = 0; while(--p > at) if(*p == '.' && ++dots >= dotlim){ p++; break; } for(; *p; p++){ if(strchr(".*+?(|)\\[]^$", *p) != nil) s_putc(s, '\\'); s_putc(s, *p); } s_terminate(s); return s; }
vlong du(char *name, Dir *dir) { int fd, i, n; Dir *buf, *d; String *file; vlong nk, t; if(dir == nil) return warn(name); if((dir->qid.type&QTDIR) == 0) return dirval(dir, blkmultiple(dir->length)); fd = open(name, OREAD); if(fd < 0) return warn(name); nk = 0; while((n=dirread(fd, &buf)) > 0) { d = buf; for(i = n; i > 0; i--, d++) { if((d->qid.type&QTDIR) == 0) { nk += dufile(name, d); continue; } if(strcmp(d->name, ".") == 0 || strcmp(d->name, "..") == 0 || /* !readflg && */ seen(d)) continue; /* don't get stuck */ file = s_copy(name); s_append(file, "/"); s_append(file, d->name); t = du(s_to_c(file), d); nk += t; t = dirval(d, t); if(!sflag) printamt(t, s_to_c(file)); s_free(file); } free(buf); } if(n < 0) warn(name); close(fd); return dirval(dir, nk); }
/* * ensure route addr has brackets around it */ String* fixrouteaddr(String *raddr, Node *next, Node *last) { String *a; if(last && last->c == '<' && next && next->c == '>') return raddr; /* properly formed already */ a = s_new(); s_append(a, "<"); s_append(a, s_to_c(raddr)); s_append(a, ">"); s_free(raddr); return a; }
/* * create abs path of the mailer */ String* mailerpath(char *p) { String *s; if(p == nil) return nil; if(*p == '/') return s_copy(p); s = s_new(); s_append(s, UPASBIN); s_append(s, "/"); s_append(s, p); return s; }
/* * Get the next token from `line'. The symbol `\l' is replaced by * the name of the local system. */ extern String * rule_parse(String *line, char *system, int *backl) { String *token; String *expanded; char *cp; token = s_parse(line, 0); if(token == 0) return(token); if(strchr(s_to_c(token), '\\')==0) return(token); expanded = s_new(); for(cp = s_to_c(token); *cp; cp++) { if(*cp == '\\') switch(*++cp) { case 'l': s_append(expanded, system); *backl = 1; break; case '\\': s_putc(expanded, '\\'); break; default: s_putc(expanded, '\\'); s_putc(expanded, *cp); break; } else s_putc(expanded, *cp); } s_free(token); s_terminate(expanded); return(expanded); }
/* * like trylock, but we've already got the lock on fd, * and don't want an L. lock file. */ static Mlock * keeplockalive(char *path, int fd) { char buf[1]; Mlock *l; l = malloc(sizeof(Mlock)); if(l == 0) return 0; l->fd = fd; l->name = s_new(); s_append(l->name, path); /* fork process to keep lock alive until sysunlock(l) */ switch(l->pid = rfork(RFPROC)){ default: break; case 0: fd = l->fd; for(;;){ sleep(1000*60); if(pread(fd, buf, 1, 0) < 0) break; } _exits(0); } return l; }
String* s_appendsub(String *s, char *p, int n, Sub *sub, int nsub) { int i, m; char *q, *r, *ep; ep = p+n; while(p<ep){ q = ep; m = -1; for(i=0; i<nsub; i++){ if(sub[i].sub && (r = strstr(p, sub[i].match)) && r < q){ q = r; m = i; } } s = s_nappend(s, p, q-p); p = q; if(m >= 0){ s = s_append(s, sub[m].sub); p += strlen(sub[m].match); } } return s; }
/* * simplify an address, reduce to a domain */ static String* simplify(char *addr) { int dots; char *p, *at; String *s; mklower(addr); at = strchr(addr, '@'); if(at == nil){ /* local address, make it an exact match */ s = s_copy("="); s_append(s, addr); return s; } /* copy up to the '@' sign */ at++; s = s_copy("~"); for(p = addr; p < at; p++){ if(strchr(".*+?(|)\\[]^$", *p)) s_putc(s, '\\'); s_putc(s, *p); } /* just any address matching the two most significant domain elements */ s_append(s, "(.*\\.)?"); p = addr+strlen(addr); dots = 0; for(; p > at; p--){ if(*p != '.') continue; if(dots++ > 0){ p++; break; } } for(; *p; p++){ if(strchr(".*+?(|)\\[]^$", *p) != 0) s_putc(s, '\\'); s_putc(s, *p); } s_terminate(s); return s; }
int smbremovefile(SmbTree *t, char *dir, char *name) { String *s; int rv; s = s_new(); s_append(s, t->serv->path); s_append(s, "/"); if (dir) { s_append(s, dir); s_append(s, "/"); } s_append(s, name); rv = remove(s_to_c(s)); s_free(s); return rv; }
extern int default_from(message *mp) { char *cp, *lp; cp = getenv("upasname"); lp = getlog(); if(lp == nil) return -1; if(cp && *cp) s_append(mp->sender, cp); else s_append(mp->sender, lp); s_append(mp->date, thedate()); return 0; }
/* loop through the translation files */ static int translate(char *name, /* name to translate */ char **namev, /* names of this system */ String *files, /* names of system alias files */ String *alias) /* where to put the alias */ { String *file = s_new(); String **fullnamev; int n, rv; rv = -1; DEBUG print("translate(%s, %s, %s)\n", name, s_to_c(files), s_to_c(alias)); /* create the full name to avoid loops (system!name) */ for(n = 0; namev[n]; n++) ; fullnamev = (String**)malloc(sizeof(String*)*(n+2)); n = 0; fullnamev[n++] = s_copy(name); for(; *namev; namev++){ fullnamev[n] = s_copy(*namev); s_append(fullnamev[n], "!"); s_append(fullnamev[n], name); n++; } fullnamev[n] = 0; /* look at system-wide names */ s_restart(files); while (s_parse(files, s_restart(file)) != 0) { if (lookup(fullnamev, file, alias)==0) { rv = 0; goto out; } } out: for(n = 0; fullnamev[n]; n++) s_free(fullnamev[n]); s_free(file); free(fullnamev); return rv; }
vlong dufile(char *name, Dir *d) { vlong t = blkmultiple(d->length); if(aflag || readflg) { String *file = s_copy(name); s_append(file, "/"); s_append(file, d->name); if (readflg) readfile(s_to_c(file)); t = dirval(d, t); printamt(t, s_to_c(file)); s_free(file); } return t; }
/* * add a domain onto an name, return the new name */ char * domainify(char *name, char *domain) { static String *s; char *p; if(domain==0 || strchr(name, '.')!=0) return name; s = s_reset(s); s_append(s, name); p = strchr(domain, '.'); if(p == 0){ s_append(s, "."); p = domain; } s_append(s, p); return s_to_c(s); }
/* * Convert from `bang' to `source routing' format. * * a.x.y!b.p.o!c!d -> @a.x.y:[email protected] */ String * bangtoat(char *addr) { String *buf; register int i; int j, d; char *field[128]; /* parse the '!' format address */ buf = s_new(); for(i = 0; addr; i++){ field[i] = addr; addr = strchr(addr, '!'); if(addr) *addr++ = 0; } if (i==1) { s_append(buf, field[0]); return buf; } /* * count leading domain fields (non-domains don't count) */ for(d = 0; d<i-1; d++) if(strchr(field[d], '.')==0) break; /* * if there are more than 1 leading domain elements, * put them in as source routing */ if(d > 1){ addhostdom(buf, field[0]); for(j=1; j<d-1; j++){ s_append(buf, ","); s_append(buf, "@"); s_append(buf, field[j]); } s_append(buf, ":"); } /* * throw in the non-domain elements separated by '!'s */ s_append(buf, field[d]); for(j=d+1; j<=i-1; j++) { s_append(buf, "!"); s_append(buf, field[j]); } if(d) addhostdom(buf, field[d-1]); return buf; }
/* * convert header addresses to @ format. * if the address is a source address, and a domain is specified, * make sure it falls in the domain. */ String* convertheader(String *from) { Field *f; Node *p, *lastp; String *a; if(!returnable(s_to_c(from))){ from = s_new(); s_append(from, "Postmaster"); addhostdom(from, hostdomain); } else if(strchr(s_to_c(from), '@') == 0){ a = username(from); if(a) { s_append(a, " <"); s_append(a, s_to_c(from)); addhostdom(a, hostdomain); s_append(a, ">"); from = a; } else { from = s_copy(s_to_c(from)); addhostdom(from, hostdomain); } } else from = s_copy(s_to_c(from)); for(f = firstfield; f; f = f->next){ lastp = 0; for(p = f->node; p; lastp = p, p = p->next){ if(!p->addr) continue; a = bangtoat(s_to_c(p->s)); s_free(p->s); if(strchr(s_to_c(a), '@') == 0) addhostdom(a, hostdomain); else if(*s_to_c(a) == '@') a = fixrouteaddr(a, p->next, lastp); p->s = a; } } return from; }
int ztns_append_llong (ztns_t *self, long long data) { uint str_len = s_get_str_len (data); char data_str[str_len + NULL_LENGTH]; int chars_written = snprintf (data_str, str_len + NULL_LENGTH, "%lld", data); assert (chars_written >= 0 || chars_written <= str_len); if (chars_written < 0 || chars_written > str_len) return -1; return s_append (self, data_str, '#'); }
int ztns_append_float (ztns_t *self, float data) { const uint MAX_FLOAT_CHARS = strlen("-0.") + FLT_MANT_DIG - FLT_MIN_EXP; char data_str[MAX_FLOAT_CHARS + NULL_LENGTH]; int chars_written = snprintf (data_str, MAX_FLOAT_CHARS + NULL_LENGTH, "%.*f", MAX_FLOAT_CHARS, data); assert (chars_written >= 0 || chars_written <= MAX_FLOAT_CHARS); if (chars_written < 0 || chars_written > MAX_FLOAT_CHARS) return -1; return s_append (self, data_str, '^'); }
/* get the text of a header line minus the field name */ static String* getstring(Node *p) { String *s; s = s_new(); if(p == nil) return s; for(p = p->next; p; p = p->next){ if(p->s){ s_append(s, s_to_c(p->s)); }else{ s_putc(s, p->c); s_terminate(s); } if(p->white) s_append(s, s_to_c(p->white)); } return s; }
String* s_appendlist(String *s, ...) { char *x; va_list arg; va_start(arg, s); while(x = va_arg(arg, char*)) s = s_append(s, x); va_end(arg); return s; }
static void addtreetoar(int ar, char *file, char *shortf, int fd) { int n; Dir *dent, *dirents; String *name = s_new(); n = dirreadall(fd, &dirents); if (n < 0) fprint(2, "%s: dirreadall %s: %r\n", argv0, file); close(fd); if (n <= 0) return; if (chdir(shortf) < 0) sysfatal("chdir %s: %r", file); if (Debug) fprint(2, "chdir %s\t# %s\n", shortf, file); for (dent = dirents; dent < dirents + n; dent++) { s_reset(name); s_append(name, file); s_append(name, "/"); s_append(name, dent->name); addtoar(ar, s_to_c(name), dent->name); } s_free(name); free(dirents); /* * this assumes that shortf is just one component, which is true * during directory descent, but not necessarily true of command-line * arguments. Our caller (or addtoar's) must reset the working * directory if necessary. */ if (chdir("..") < 0) sysfatal("chdir %s/..: %r", file); if (Debug) fprint(2, "chdir ..\n"); }
int matcher(char *action, Pattern *p, char *message, Resub *m) { char *cp; String *s; for(cp = message; matchpat(p, cp, m); cp = m->ep) { switch(p->action) { case SaveLine: if(vflag) xprint(2, action, m); saveline(linefile, sender, m); break; case HoldHeader: case Hold: if(nflag) continue; if(vflag) xprint(2, action, m); *qdir = holdqueue; if(hflag && qname) { cp = strchr(sender, '!'); if(cp) { *cp = 0; *qname = strdup(sender); *cp = '!'; } else *qname = strdup(sender); } return 1; case Dump: if(vflag) xprint(2, action, m); *(m->ep) = 0; if(!tflag) { s = s_new(); s_append(s, sender); s = unescapespecial(s); syslog(0, "smtpd", "Dumped %s [%s] to %s", s_to_c(s), m->sp, s_to_c(s_restart(recips))); s_free(s); } tflag = 1; if(sflag) cout = opendump(sender); return 1; default: break; } } return 0; }