static void dovalidate(void) { const char *name; int fd, i, mykeys, keys_done, keys_to_do; int key, smallest, largest; name = PATH_SORTED; fd = doopen(name, O_RDONLY, 0); mykeys = getmykeys(); seekmyplace(name, fd); smallest = RANDOM_MAX; largest = 0; keys_done = 0; while (keys_done < mykeys) { keys_to_do = mykeys - keys_done; if (keys_to_do > WORKNUM) { keys_to_do = WORKNUM; } doexactread(name, fd, workspace, keys_to_do * sizeof(int)); for (i=0; i<keys_to_do; i++) { key = workspace[i]; if (key < 0) { complain("%s: found negative key", name); exit(1); } if (key == 0) { complain("%s: found zero key", name); exit(1); } if (key >= RANDOM_MAX) { complain("%s: found too-large key", name); exit(1); } if (key < smallest) { smallest = key; } if (key > largest) { largest = key; } } keys_done += keys_to_do; } doclose(name, fd); name = validname(me); fd = doopen(name, O_WRONLY|O_CREAT|O_TRUNC, 0664); dowrite(name, fd, &smallest, sizeof(smallest)); dowrite(name, fd, &largest, sizeof(largest)); doclose(name, fd); }
static void bin(void) { int infd, outfds[numprocs]; const char *name; int i, mykeys, keys_done, keys_to_do; int key, pivot, binnum; infd = doopen(PATH_KEYS, O_RDONLY, 0); mykeys = getmykeys(); seekmyplace(PATH_KEYS, infd); for (i=0; i<numprocs; i++) { name = binname(me, i); outfds[i] = doopen(name, O_WRONLY|O_CREAT|O_TRUNC, 0664); } pivot = (RANDOM_MAX / numprocs); keys_done = 0; while (keys_done < mykeys) { keys_to_do = mykeys - keys_done; if (keys_to_do > WORKNUM) { keys_to_do = WORKNUM; } doexactread(PATH_KEYS, infd, workspace, keys_to_do * sizeof(int)); for (i=0; i<keys_to_do; i++) { key = workspace[i]; binnum = key / pivot; if (key <= 0) { complainx("proc %d: garbage key %d", me, key); key = 0; } assert(binnum >= 0); assert(binnum < numprocs); dowrite("bin", outfds[binnum], &key, sizeof(key)); } keys_done += keys_to_do; } doclose(PATH_KEYS, infd); for (i=0; i<numprocs; i++) { doclose(binname(me, i), outfds[i]); } }
static void assemble(void) { off_t mypos; int i, fd; const char *args[3]; mypos = 0; for (i=0; i<me; i++) { mypos += getsize(mergedname(i)); } fd = doopen(PATH_SORTED, O_WRONLY, 0); dolseek(PATH_SORTED, fd, mypos, SEEK_SET); if (dup2(fd, STDOUT_FILENO) < 0) { complain("dup2"); exit(1); } doclose(PATH_SORTED, fd); args[0] = "cat"; args[1] = mergedname(me); args[2] = NULL; execv("/bin/cat", (char **) args); complain("/bin/cat: exec"); exit(1); }
static void docreate(const char *file, const char *sizespec, int doforce) { int fd; off_t size; if (!doforce) { fd = open(file, O_RDONLY); if (fd >= 0) { fprintf(stderr, "disk161: %s: %s\n", file, strerror(EEXIST)); exit(1); } } fd = doopen(file, O_RDWR|O_CREAT|O_TRUNC, 0664); doflock(file, fd, LOCK_EX); size = getsize(sizespec); checksize(size); dotruncate(file, fd, HEADERSIZE + size); writeheader(file, fd); doflock(file, fd, LOCK_UN); close(fd); }
static void sortbins(void) { const char *name; int i, fd; off_t binsize; for (i=0; i<numprocs; i++) { name = binname(me, i); binsize = getsize(name); if (binsize % sizeof(int) != 0) { complainx("%s: bin size %ld no good", name, (long) binsize); exit(1); } if (binsize > (off_t) sizeof(workspace)) { complainx("proc %d: %s: bin too large", me, name); exit(1); } fd = doopen(name, O_RDWR, 0); doexactread(name, fd, workspace, binsize); sortints(workspace, binsize/sizeof(int)); dolseek(name, fd, 0, SEEK_SET); dowrite(name, fd, workspace, binsize); doclose(name, fd); } }
/* * the database entry in 'file' indicates the list of files * that makeup the database. Open each one and search in * the same order. */ struct ndb* ndbopen(char *file) { struct ndb *db, *first, *last; struct ndbs s; struct ndbtuple *t, *nt; if(file == 0) file = deffile; db = doopen(file); if(db == 0) { return 0; } first = last = db; t = ndbsearch(db, &s, "database", ""); fseek(db->b, 0, 0); if(t == 0) { return db; } for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "file") != 0) continue; if(strcmp(nt->val, file) == 0){ /* default file can be reordered in the list */ if(first->next == 0) continue; if(strcmp(first->file, file) == 0){ db = first; first = first->next; last->next = db; db->next = 0; last = db; } continue; } db = doopen(nt->val); if(db == 0) continue; last->next = db; last = db; } ndbfree(t); return first; }
static void docreate(const char *path) { int fd; fd = doopen(path, O_WRONLY|O_CREAT|O_TRUNC, 0664); doclose(path, fd); }
static void cat(void) { pid_t pid; int rfd, wfd, result, status; const char *args[2]; rfd = doopen(INFILE, O_RDONLY); wfd = doopen(OUTFILE, O_WRONLY|O_CREAT|O_TRUNC); pid = fork(); if (pid < 0) { err(1, "fork"); } if (pid == 0) { /* child */ dodup2(rfd, STDIN_FILENO, INFILE); dodup2(wfd, STDOUT_FILENO, OUTFILE); doclose(rfd, INFILE); doclose(wfd, OUTFILE); args[0] = "cat"; args[1] = NULL; execv(PATH_CAT, (char **)args); warn("%s: execv", PATH_CAT); _exit(1); } /* parent */ doclose(rfd, INFILE); doclose(wfd, OUTFILE); result = waitpid(pid, &status, 0); if (result == -1) { err(1, "waitpid"); } if (WIFSIGNALED(status)) { errx(1, "pid %d: Signal %d", (int)pid, WTERMSIG(status)); } if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { errx(1, "pid %d: Exit %d", (int)pid, WEXITSTATUS(status)); } }
static void randomize(void) { int fd; fd = doopen(PATH_RANDOM, O_RDONLY, 0); doexactread(PATH_RANDOM, fd, &randomseed, sizeof(randomseed)); doclose(PATH_RANDOM, fd); }
static void doresize(const char *file, const char *sizespec) { enum { M_SET, M_PLUS, M_MINUS } mode; off_t oldsize, newsize; int fd; if (*sizespec == '+') { sizespec++; mode = M_PLUS; } else if (*sizespec == '-') { sizespec++; mode = M_MINUS; } else { mode = M_SET; } newsize = getsize(sizespec); fd = doopen(file, O_RDWR, 0); doflock(file, fd, LOCK_EX); checkheader(file, fd); oldsize = filesize(file, fd); oldsize -= HEADERSIZE; switch (mode) { case M_SET: break; case M_PLUS: if (oldsize + newsize < oldsize) { /* overflow */ fprintf(stderr, "+%s: Result too large\n", sizespec); exit(1); } newsize = oldsize + newsize; break; case M_MINUS: if (oldsize < newsize) { /* underflow */ fprintf(stderr, "-%s: Result too small\n", sizespec); exit(1); } newsize = oldsize - newsize; break; } checksize(newsize); dotruncate(file, fd, HEADERSIZE + newsize); doflock(file, fd, LOCK_UN); close(fd); }
static void validate(void) { int smallest, largest, prev_largest; int i, fd; const char *name; doforkall("Validation", dovalidate); checksize_valid(); prev_largest = 1; for (i=0; i<numprocs; i++) { name = validname(i); fd = doopen(name, O_RDONLY, 0); doexactread(name, fd, &smallest, sizeof(int)); doexactread(name, fd, &largest, sizeof(int)); if (smallest < 1) { complainx("Validation: block %d: bad SMALLEST", i); exit(1); } if (largest >= RANDOM_MAX) { complainx("Validation: block %d: bad LARGEST", i); exit(1); } if (smallest > largest) { complainx("Validation: block %d: SMALLEST > LARGEST", i); exit(1); } if (smallest < prev_largest) { complain("Validation: block %d smallest key %d", i, smallest); complain("Validation: previous block largest key %d", prev_largest); complain("Validation failed"); exit(1); } } for (i=0; i<numprocs; i++) { doremove(validname(i)); } }
static off_t getsize(const char *path) { struct stat buf; int fd; static int no_stat, no_fstat; if (!no_stat) { if (stat(path, &buf) == 0) { return buf.st_size; } if (errno != ENOSYS) { complain("%s: stat", path); exit(1); } /* Avoid further "Unknown syscall 81" messages */ no_stat = 1; } fd = doopen(path, O_RDONLY, 0); if (!no_fstat) { if (fstat(fd, &buf) == 0) { close(fd); return buf.st_size; } if (errno != ENOSYS) { complain("%s: stat", path); exit(1); } /* Avoid further "Unknown syscall 82" messages */ no_fstat = 1; } /* otherwise, lseek */ if (lseek(fd, 0, SEEK_END) >= 0) { buf.st_size = lseek(fd, 0, SEEK_CUR); if (buf.st_size >= 0) { return buf.st_size; } } complain("%s: getting file size with lseek", path); close(fd); exit(1); }
void writefile(const char *to_write, const char *from, const char *to, const char *mode) { int ofd; if (strcmp("-", to_write) == 0) { ofd = 1; // stdout } else { ofd = doopen(to_write, mode); } ssize_t towrite = to - from; ssize_t written = write(ofd, from, towrite); if (written != towrite) { fprintf(stderr, "Expected to write %li bytes but %li written\n", towrite, written); perror(to_write); exit(EXIT_FAILURE); } if (ofd != 1) close(ofd); } // writefile()
static void mkfile(void) { int fd; ssize_t r; fd = doopen(INFILE, O_WRONLY|O_CREAT|O_TRUNC); r = write(fd, slogan, strlen(slogan)); if (r < 0) { err(1, "%s: write", INFILE); } if ((size_t)r != strlen(slogan)) { errx(1, "%s: write: Short count (got %zd, expected %zu)", INFILE, r, strlen(slogan)); } doclose(fd, INFILE); }
static unsigned long checksum_file(const char *path) { int fd; char buf[512]; size_t count, i; unsigned long sum = 0; fd = doopen(path, O_RDONLY, 0); while ((count = doread(path, fd, buf, sizeof(buf))) > 0) { for (i=0; i<count; i++) { sum += (unsigned char) buf[i]; } } doclose(path, fd); return sum; }
static void genkeys_sub(void) { int fd, i, mykeys, keys_done, keys_to_do, value; fd = doopen(PATH_KEYS, O_WRONLY, 0); mykeys = getmykeys(); seekmyplace(PATH_KEYS, fd); srandom(seeds[me]); keys_done = 0; while (keys_done < mykeys) { keys_to_do = mykeys - keys_done; if (keys_to_do > WORKNUM) { keys_to_do = WORKNUM; } for (i=0; i<keys_to_do; i++) { value = random(); // check bounds of value assert(value >= 0); assert(value <= RANDOM_MAX); // do not allow the value to be zero or RANDOM_MAX while (value == 0 || value == RANDOM_MAX) { value = random(); } workspace[i] = value; } dowrite(PATH_KEYS, fd, workspace, keys_to_do*sizeof(int)); keys_done += keys_to_do; } doclose(PATH_KEYS, fd); }
static void doinfo(const char *file) { int fd; struct stat st; long long amt; fd = doopen(file, O_RDWR, 0); checkheader(file, fd); dofstat(file, fd, &st); amt = st.st_size - HEADERSIZE; printf("%s size %lld bytes (%lld sectors; %lldK; %lldM)\n", file, amt, amt / SECTORSIZE, amt / 1024, amt / (1024*1024)); amt = st.st_blocks * 512LL; printf("%s spaceused %lld bytes (%lld sectors; %lldK; %lldM)\n", file, amt, amt / SECTORSIZE, amt / 1024, amt / (1024*1024)); close(fd); }
static void chkfile(void) { char buf[256]; ssize_t r; int fd; fd = doopen(OUTFILE, O_RDONLY); r = read(fd, buf, sizeof(buf)); if (r < 0) { err(1, "%s: read", OUTFILE); } if (r == 0) { errx(1, "%s: read: Unexpected EOF", OUTFILE); } if ((size_t)r != strlen(slogan)) { errx(1, "%s: read: Short count (got %zd, expected %zu)", OUTFILE, r, strlen(slogan)); } doclose(fd, OUTFILE); }
/* * Print mail entries */ void printmail() { static char pn[] = "printmail"; int flg, curlet, showlet, k, print, aret, stret, rc; int nsmbox = 0; /* 1 ==> mailbox is in non-standard place */ int sav_j = -1; char *p, *getarg(); struct stat stbuf; struct stat *stbufp; int ttyf = isatty(1) ? TTY : ORDINARY; char readbuf[LSIZE]; /* holds user's response in interactive mode */ char *resp; gid_t savedegid; stbufp = &stbuf; /* * create working directory mbox name */ if ((hmbox = malloc(strlen(home) + strlen(mbox) + 1)) == NULL) { errmsg(E_MBOX, ""); return; } cat(hmbox, home, mbox); /* * If we are not using an alternate mailfile, then get * the $MAIL value and build the filename for the mailfile. * If $MAIL is set, but is NOT the 'standard' place, then * use it but set flgf to circumvent :saved processing. */ if (!flgf) { if ((p = malloc(strlen(maildir) + strlen(my_name) + 1)) == NULL) { errmsg(E_MEM, ""); return; } cat(p, maildir, my_name); if (((mailfile = getenv("MAIL")) == NULL) || (strlen(mailfile) == 0)) { /* $MAIL not set, use standard path to mailfile */ mailfile = p; } else { if (strcmp(mailfile, p) != 0) { flgf = 1; nsmbox = 1; Dout(pn, 0, "$MAIL ('%s') != standard path\n", mailfile); Dout("", 0, "\tSetting flgf to 1.\n"); } free(p); } } /* * Get ACCESS and MODIFICATION times of mailfile BEFORE we * use it. This allows us to put them back when we are * done. If we didn't, the shell would think NEW mail had * arrived since the file times would have changed. */ stret = CERROR; if (access(mailfile, A_EXIST) == A_OK) { if ((stret = stat(mailfile, stbufp)) != A_OK) { errmsg(E_FILE, "Cannot stat mailfile"); return; } mf_gid = stbufp->st_gid; mf_uid = stbufp->st_uid; utimep->actime = stbufp->st_atime; utimep->modtime = stbufp->st_mtime; file_size = stbufp->st_size; } /* Open the file as the real gid */ savedegid = getegid(); (void) setegid(getgid()); malf = fopen(mailfile, "r"); (void) setegid(savedegid); /* * stat succeeded, but we cannot access the mailfile */ if (stret == CSUCCESS && malf == NULL) { char buf[MAXFILENAME+50]; (void) snprintf(buf, sizeof (buf), "Invalid permissions on %s", mailfile); errmsg(E_PERM, buf); return; } else /* * using an alternate mailfile, but we failed on access */ if (!nsmbox && flgf && (malf == NULL)) { errmsg(E_FILE, "Cannot open mailfile"); return; } /* * we failed to access OR the file is empty */ else if ((malf == NULL) || (stbuf.st_size == 0)) { if (!flge && !flgE) { printf("No mail.\n"); } error = E_FLGE; Dout(pn, 0, "error set to %d\n", error); return; } if (flge) return; if (flgE) { if (utimep->modtime < utimep->actime) { error = E_FLGE_OM; Dout(pn, 0, "error set to %d\n", error); } return; } /* * Secure the mailfile to guarantee integrity */ lock(my_name); /* * copy mail to temp file and mark each letter in the * let array --- mailfile is still locked !!! */ mktmp(); copymt(malf, tmpf); onlet = nlet; fclose(malf); fclose(tmpf); unlock(); /* All done, OK to unlock now */ tmpf = doopen(lettmp, "r+", E_TMP); changed = 0; print = 1; curlet = 0; while (curlet < nlet) { /* * reverse order ? */ showlet = flgr ? curlet : nlet - curlet - 1; if (setjmp(sjbuf) == 0 && print != 0) { /* -h says to print the headers first */ if (flgh) { gethead(showlet, 0); flgh = 0; /* Only once */ /* set letter # to invalid # */ curlet--; showlet = flgr ? curlet : nlet - curlet - 1; } else { if (showlet != sav_j) { /* Looking at new message. */ /* Reset flag to override */ /* non-display of binary */ /* contents */ sav_j = showlet; pflg = 0; Pflg = flgP; } copylet(showlet, stdout, ttyf); } } /* * print only */ if (flgp) { curlet++; continue; } /* * Interactive */ interactive = 1; setjmp(sjbuf); stat(mailfile, stbufp); if (stbufp->st_size != file_size) { /* * New mail has arrived, load it */ k = nlet; lock(my_name); malf = doopen(mailfile, "r", E_FILE); fclose(tmpf); tmpf = doopen(lettmp, "a", E_TMP); fseek(malf, let[nlet].adr, 0); copymt(malf, tmpf); file_size = stbufp->st_size; fclose(malf); fclose(tmpf); unlock(); tmpf = doopen(lettmp, "r+", E_TMP); if (++k < nlet) printf("New mail loaded into letters %d - %d\n", k, nlet); else printf("New mail loaded into letter %d\n", nlet); } /* read the command */ printf("? "); fflush(stdout); fflush(stderr); if (fgets(readbuf, sizeof (readbuf), stdin) == NULL) break; resp = readbuf; while (*resp == ' ' || *resp == '\t') resp++; print = 1; Dout(pn, 0, "resp = '%s'\n", resp); if ((rc = atoi(resp)) != 0) { if (!validmsg(rc)) print = 0; else curlet = flgr ? rc - 1 : nlet - rc; } else switch (resp[0]) { default: printf("Usage:\n"); /* * help */ case '?': print = 0; for (rc = 0; help[rc]; rc++) printf("%s", help[rc]); break; /* * print message number of current message */ case '#': print = 0; if ((showlet == nlet) || (showlet < 0)) { printf("No message selected yet.\n"); } else { printf("Current message number is %d\n", showlet+1); } break; /* * headers */ case 'h': print = 0; if (resp[2] != 'd' && resp[2] != 'a' && (rc = getnumbr(resp+1)) > 0) { showlet = rc - 1; curlet = flgr ? rc - 1 : nlet - rc- 1; } if (rc == -1 && resp[2] != 'a' && resp[2] != 'd') break; if (resp[2] == 'a') rc = 1; else if (resp[2] == 'd') rc = 2; else rc = 0; /* * if (!validmsg(showlet)) break; */ gethead(showlet, rc); break; /* * skip entry */ case '+': case 'n': case '\n': curlet++; break; case 'P': Pflg++; break; case 'p': pflg++; break; case 'x': changed = 0; case 'q': goto donep; /* * Previous entry */ case '^': case '-': if (--curlet < 0) curlet = 0; break; /* * Save in file without header */ case 'y': case 'w': /* * Save mail with header */ case 's': print = 0; if (!validmsg(curlet)) break; if (resp[1] == '\n' || resp[1] == '\0') { cat(resp+1, hmbox, ""); } else if (resp[1] != ' ') { printf("Invalid command\n"); break; } umask(umsave); flg = 0; if (getarg(lfil, resp + 1) == NULL) { cat(resp + 1, hmbox, ""); } malf = (FILE *)NULL; p = resp + 1; while ((p = getarg(lfil, p)) != NULL) { if (flg) { fprintf(stderr, "%s: File '%s' skipped\n", program, lfil); continue; } malf = NULL; if ((aret = legal(lfil))) { malf = fopen(lfil, "a"); } if ((malf == NULL) || (aret == 0)) { fprintf(stderr, "%s: Cannot append to %s\n", program, lfil); flg++; } else if (aret == 2) { chown(lfil, my_euid, my_gid); } if (!flg && copylet(showlet, malf, resp[0] == 's'? ORDINARY: ZAP) == FALSE) { fprintf(stderr, "%s: Cannot save mail to '%s'\n", program, lfil); flg++; } else Dout(pn, 0, "!saved\n"); if (malf != (FILE *)NULL) { fclose(malf); } } umask(7); if (!flg) { setletr(showlet, resp[0]); print = 1; curlet++; } break; /* * Reply to a letter */ case 'r': print = 0; if (!validmsg(curlet)) break; replying = 1; for (k = 1; resp[k] == ' ' || resp[k] == '\t'; ++k); resp[strlen(resp)-1] = '\0'; (void) strlcpy(m_sendto, resp+k, sizeof (m_sendto)); goback(showlet); replying = 0; setletr(showlet, resp[0]); break; /* * Undelete */ case 'u': print = 0; if ((k = getnumbr(resp+1)) <= 0) k = showlet; else k--; if (!validmsg(k)) break; setletr(k, ' '); break; /* * Mail letter to someone else */ case 'm': { reciplist list; print = 0; if (!validmsg(curlet)) break; new_reciplist(&list); flg = 0; k = 0; if (substr(resp, " -") != -1 || substr(resp, "\t-") != -1) { printf("Only users may be specified\n"); break; } p = resp + 1; while ((p = getarg(lfil, p)) != NULL) { char *env; if (lfil[0] == '$') { if (!(env = getenv(&lfil[1]))) { fprintf(stderr, "%s: %s has no value or is not exported.\n", program, lfil); flg++; } else add_recip(&list, env, FALSE); k++; } else if (lfil[0] != '\0') { add_recip(&list, lfil, FALSE); k++; } } (void) strlcpy(Rpath, my_name, sizeof (Rpath)); sending = TRUE; flg += sendlist(&list, showlet, 0); sending = FALSE; if (k) { if (!flg) { setletr(showlet, 'm'); print = 1; curlet++; } } else printf("Invalid command\n"); del_reciplist(&list); break; } /* * Read new letters */ case 'a': if (onlet == nlet) { printf("No new mail\n"); print = 0; break; } curlet = 0; print = 1; break; /* * Escape to shell */ case '!': systm(resp + 1); printf("!\n"); print = 0; break; /* * Delete an entry */ case 'd': print = 0; k = 0; if (strncmp("dq", resp, 2) != SAME && strncmp("dp", resp, 2) != SAME) if ((k = getnumbr(resp+1)) == -1) break; if (k == 0) { k = showlet; if (!validmsg(curlet)) break; print = 1; curlet++; } else k--; setletr(k, 'd'); if (resp[1] == 'p') print = 1; else if (resp[1] == 'q') goto donep; break; } } /* * Copy updated mailfile back */ donep: if (changed) { copyback(); stamp(); } }
static void* cacheopen(char const* url) { const char* basename = strrchr(url,'/'); assert(basename); static char dest[508]; snprintf(dest,508,"%s/%s",cacheDir,basename); bool didtemp = false; int doopen(void) { int result = open(dest,O_RDONLY); if(result<0) { char temp[512]; snprintf(temp,512,"%s.temp",dest); if(xmlIOHTTPMatch(url)) { void* ctx = NULL; #if W3_ARE_NOT_MORONS ctx = xmlNanoHTTPOpen(url, NULL); if(xmlNanoHTTPReturnCode(ctx) != 200) #else if(true) #endif { // XXX: it always is... w3.org dies on HTTP/1.0 #if W3_ARE_NOT_MORONS xmlNanoHTTPClose(ctx); #endif fprintf(stderr,"Curl fallback for %s\n",url); int pid = fork(); if(pid == 0) { execlp("curl","curl","-o",temp,url,NULL); abort(); } int status = 0; waitpid(pid,&status,0); if(!(WIFEXITED(status) && (0 == WEXITSTATUS(status)))) { fprintf(stderr,"CUrl failed! %x %d\n",status,WEXITSTATUS(status)); abort(); } } else { assert(0==xmlNanoHTTPSave(ctx,temp)); } } else if(xmlIOFTPMatch(url)) { void* ftp = xmlNanoFTPOpen(url); int out = open(temp,O_WRONLY|O_TRUNC|O_CREAT,0644); assert(out>0); char buf[0x1000]; for(;;) { int amt = xmlNanoFTPRead(ftp, buf, 0x1000); if(amt==0) break; assert(amt>0); write(out,buf,amt); } close(out); } else { FILE* fp = xmlFileOpen(url); struct stat fpstat; if(!fp) { fprintf(stderr,"No idea what to do with url %s\n",url); abort(); } int inp = fileno(fp); assert(0==fstat(inp,&fpstat)); off_t left = fpstat.st_size; int out = open(temp,O_WRONLY|O_TRUNC|O_CREAT,0644); assert(out>0); do { ssize_t amt = sendfile(out,inp,NULL,left); if(amt<0) { perror(url); } assert(amt>=0); left -= amt; } while(left > 0); fclose(fp); close(out); } rename(temp,dest); // doesn't matter if fails unlink(temp); // in case it failed return doopen(); } return result; }
/* Send mail - High level sending routine */ void sendmail(int argc, char **argv) { char **args; char *tp, *zp; char *buf = NULL; size_t bufsize = 0; char last1c; FILE *input; struct stat sbuf; int aret; int i, n; int oldn = 1; int ttyf = 0; int pushrest = 0; int hdrtyp = 0; int ctf = FALSE; int binflg = 0; long count = 0L; struct tm *bp; struct hdrs *hptr; static char pn[] = "sendmail"; reciplist list; buf = smalloc(bufsize = 2048); Dout(pn, 0, "entered\n"); new_reciplist(&list); for (i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (argv[i][1] == '\0') { errmsg(E_SYNTAX,"Hyphens MAY NOT be followed by spaces"); } if (i > 1) { errmsg(E_SYNTAX,"Options MUST PRECEDE persons"); } done(0); } /* Ensure no NULL names in list */ if (argv[i][0] == '\0' || argv[i][strlen(argv[i])-1] == '!') { errmsg(E_SYNTAX,"Null names are not allowed"); done(0); } add_recip(&list, argv[i], FALSE); /* Don't check for duplication */ } mktmp(); /* Format time */ time(&iop); bp = localtime(&iop); tp = asctime(bp); zp = tzname[bp->tm_isdst]; sprintf(datestring, "%.16s %.4s %.5s", tp, zp, tp+20); trimnl (datestring); /* asctime: Fri Sep 30 00:00:00 1986\n */ /* 0123456789012345678901234 */ /* RFCtime: Fri, 28 Jul 89 10:30 EDT */ sprintf(RFC822datestring, "%.3s, %.2s %.3s %.4s %.5s %.3s", tp, tp+8, tp+4, tp+20, tp+11, zp); /* Write out the from line header for the letter */ if (fromflag && deliverflag && from_user[0] != '\0') { snprintf(buf, bufsize, "%s%s %s\n", header[H_FROM].tag, from_user, datestring); } else { snprintf(buf, bufsize, "%s%s %s\n", header[H_FROM].tag, my_name, datestring); } if (!wtmpf(buf, strlen(buf))) { done(0); } savehdrs(buf, H_FROM); /* Copy to list in mail entry? */ if (flgt == 1 && argc > 1) { aret = argc; args = argv; while (--aret > 0) { snprintf(buf, bufsize, "%s %s\n", header[H_TO].tag, *++args); if (!wtmpf(buf, strlen(buf))) { done(0); } savehdrs(buf, H_TO); } } flgf = 1; /* reset when first read of message body succeeds */ /* Read mail message, allowing for lines of infinite length. This is tricky, have to watch for newlines. */ saveint = setsig(SIGINT, savdead); last1c = ' '; /* anything other than newline */ ttyf = isatty (fileno(stdin)); pushrest = 0; /* * scan header & save relevant info. */ cpy(&fromU, &fromUsize, my_name); cpy(&fromS, &fromSsize, ""); input = stdin; if (fstat(fileno(input), &sbuf) < 0) { #ifdef EOVERFLOW if (errno == EOVERFLOW) { perror("stdin"); exit(1); } #endif } while ((n = getline (&line, &linesize, stdin)) > 0) { last1c = line[n-1]; if (pushrest) { if (!wtmpf(line,n)) { done(0); } pushrest = (last1c != '\n'); continue; } pushrest = (last1c != '\n'); if ((hdrtyp = isheader (line, &ctf)) == FALSE) { break; } flgf = 0; switch (hdrtyp) { case H_RVERS: /* Are we dealing with a delivery report? */ /* dflag = 9 ==> do not return on failure */ dflag = 9; Dout(pn, 0, "dflag = 9\n"); break; case H_FROM: if (!wtmpf(">", 1)) { done(0); } /* note dropthru */ hdrtyp = H_FROM1; case H_FROM1: if (substr(line, "forwarded by") > -1) { break; } pickFrom (line); if (Rpath[0] != '\0') concat(&Rpath, &Rpathsize, "!"); concat(&Rpath, &Rpathsize, fromS); n = 0; /* don't copy remote from's into mesg. */ break; case H_CTYPE: /* suppress it: only generated if needed */ n = 0; /* suppress */ break; case H_TCOPY: /* Write out placeholder for later */ snprintf(buf, bufsize, "%s \n", header[H_TCOPY].tag); if (!wtmpf(buf, strlen(buf))) { done(0); } n = 0; /* suppress */ break; case H_MTYPE: if (flgm) { /* suppress if message-type argument */ n = 0; } break; case H_CONT: if (oldn == 0) { /* suppress continuation line also */ n = 0; } break; } oldn = n; /* remember if this line was suppressed */ if (n && !wtmpf(line,n)) { done(0); } if (!n) savehdrs(line, hdrtyp); } if (Rpath != NULL && Rpath[0] != '\0') concat(&Rpath, &Rpathsize, "!"); concat(&Rpath, &Rpathsize, fromU); /* push out message type if so requested */ if (flgm) { /* message-type */ snprintf(buf, bufsize, "%s%s\n", header[H_MTYPE].tag, msgtype); if (!wtmpf(buf, strlen(buf))) { done(0); } } if (n > bufsize) { free(buf); buf = smalloc(bufsize = n); } memcpy (buf, line, n); if (n == 0 || (ttyf && !strncmp (buf, ".\n", 2)) ) { if (flgf) { /* no input */ return; } else { /* * no content: put content-type * only if explicitly present. * Write out 'place-holders' only. (see below....) */ if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { snprintf(line, linesize, "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } } goto wrapsend; } } if (n == 1 && last1c == '\n') { /* blank line -- suppress */ n = getline (&buf, &bufsize, stdin); if (n == 0 || (ttyf && !strncmp (buf, ".\n", 2)) ) { /* * no content: put content-type * only if explicitly present. * Write out 'place-holder' only. (see below....) */ if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { snprintf(line, linesize, "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } } goto wrapsend; } } if (debug > 0) { buf[n] = '\0'; Dout(pn, 0, "header scan complete, readahead %d = \"%s\"\n", n, buf); } /* * Write out H_CTYPE line. This is used only as * placeholders in the tmp file. When the 'real' message is sent, * the proper value will be put out by copylet(). */ snprintf(line, linesize, "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } if (hdrlines[H_CTYPE].head == (struct hdrs *)NULL) { savehdrs(line,H_CTYPE); } /* and a blank line */ if (!wtmpf("\n", 1)) { done(0); } Dout(pn, 0, "header out completed\n"); pushrest = 0; count = 0L; /* * Are we returning mail from a delivery failure of an old-style * (SVR3.1 or SVR3.0) rmail? If so, we won't return THIS on failure * [This line should occur as the FIRST non-blank non-header line] */ if (!strncmp("***** UNDELIVERABLE MAIL sent to",buf,32)) { dflag = 9; /* 9 says do not return on failure */ Dout(pn, 0, "found old-style UNDELIVERABLE line. dflag = 9\n"); } /* scan body of message */ while (n > 0) { if (ttyf && !strcmp (buf, ".\n")) break; if (!binflg) { binflg = !istext ((unsigned char *)buf, n); } if (!wtmpf(buf, n)) { done(0); } count += n; n = ttyf ? getline (&buf, &bufsize, stdin) : fread (buf, 1, bufsize, stdin); } setsig(SIGINT, saveint); wrapsend: /* * In order to use some of the subroutines that are used to * read mail, the let array must be set up */ nlet = 1; let[0].adr = 0; let[1].adr = ftell(tmpf); let[0].text = (binflg == 1 ? FALSE : TRUE); Dout(pn, 0, "body copy complete, count %ld\n", count); /* * Modify value of H_CTYPE if necessary. */ if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { if (strlen(hptr->value) == 0) strcpy(hptr->value, binflg ? "binary" : "text"); } if (fclose(tmpf) == EOF) { tmpf = NULL; tmperr(); done(0); } tmpf = doopen(lettmp,"r+",E_TMP); /* Do not send mail on SIGINT */ if (dflag == 2) { done(0); } sendlist(&list, 0, 0); done(0); }
static void mergebins(void) { int infds[numprocs], outfd; int values[numprocs], ready[numprocs]; const char *name, *outname; int i, result; int numready, place, val, worknum; outname = mergedname(me); outfd = doopen(outname, O_WRONLY|O_CREAT|O_TRUNC, 0664); for (i=0; i<numprocs; i++) { name = binname(i, me); infds[i] = doopen(name, O_RDONLY, 0); values[i] = 0; ready[i] = 0; } worknum = 0; while (1) { numready = 0; for (i=0; i<numprocs; i++) { if (infds[i] < 0) { continue; } if (!ready[i]) { result = doread("bin", infds[i], &val, sizeof(int)); if (result == 0) { doclose("bin", infds[i]); infds[i] = -1; continue; } if ((size_t) result != sizeof(int)) { complainx("%s: read: short count", binname(i, me)); exit(1); } values[i] = val; ready[i] = 1; } numready++; } if (numready == 0) { break; } /* find the smallest */ place = -1; for (i=0; i<numprocs; i++) { if (!ready[i]) { continue; } if (place < 0 || values[i] < val) { val = values[i]; place = i; } } assert(place >= 0); workspace[worknum++] = val; if (worknum >= WORKNUM) { assert(worknum == WORKNUM); dowrite(outname, outfd, workspace, worknum * sizeof(int)); worknum = 0; } ready[place] = 0; } dowrite(outname, outfd, workspace, worknum * sizeof(int)); doclose(outname, outfd); for (i=0; i<numprocs; i++) { assert(infds[i] < 0); } }