int main() { printf("%s\n", maketemp(123, "helhelele", 32).y); doit(maketemp(123, "hello world", 456), 1); printf("%d\n", doit( maketemp(123, "hello world", 456), 0 ).x); printf("%s\n", doit( maketemp(123, "hello world", 456), 0 ).y); printf("%d\n", doit( maketemp(123, "hello world", 456), 0 ).z); }
static int herein(struct ioword *iop, char **resbuf) { int fd = -1; struct shf *shf; struct temp *h; int i; /* ksh -c 'cat << EOF' can cause this... */ if (iop->heredoc == NULL) { warningf(true, "%s missing", "here document"); /* special to iosetup(): don't print error */ return (-2); } /* lexer substitution flags */ i = (iop->flag & IOEVAL) ? (ONEWORD | HEREDOC) : 0; /* skip all the fd setup if we just want the value */ if (resbuf != NULL) return (hereinval(iop->heredoc, i, resbuf, NULL)); /* * Create temp file to hold content (done before newenv * so temp doesn't get removed too soon). */ h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps); if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY, 0)) < 0) { i = errno; warningf(true, "can't %s temporary file %s: %s", !shf ? "create" : "open", h->tffn, cstrerror(i)); if (shf) shf_close(shf); /* special to iosetup(): don't print error */ return (-2); } if (hereinval(iop->heredoc, i, NULL, shf) == -2) { close(fd); /* special to iosetup(): don't print error */ return (-2); } if (shf_close(shf) == EOF) { i = errno; close(fd); warningf(true, "can't %s temporary file %s: %s", "write", h->tffn, cstrerror(i)); /* special to iosetup(): don't print error */ return (-2); } return (fd); }
int main(int argc,char *argv[]) { register int m,n; register char *p; struct stat statx; int mode; uid_t effuid; gid_t effgid; NOT_USED(argc); arglist = argv; if((command = argv[1]) == 0) error_exit(badexec); ruserid = getuid(); euserid = geteuid(); rgroupid = getgid(); egroupid = getegid(); p = argv[0]; #ifndef _lib_setreuid maketemp(tmpname); if(strcmp(p,tmpname)==0) { /* At this point, the presumption is that we are the * version of THISPROG copied into /tmp, with the owner, * group, and setuid/gid bits correctly set. This copy of * the program is executable by anyone, so we must be careful * not to allow just any invocation of it to succeed, since * it is setuid/gid. Validate the proper execution by * examining the FDVERIFY file descriptor -- if it is owned * by root and is mode SPECIAL, then this is proof that it was * passed by a program with superuser privileges -- hence we * can presume legitimacy. Otherwise, bail out, as we suspect * an impostor. */ if(fstat(FDVERIFY,&statb) < 0 || statb.st_uid != 0 || (statb.st_mode & ~S_IFMT) != SPECIAL || close(FDVERIFY)<0) error_exit(badexec); /* This enables the grandchild to clean up /tmp file */ close(FDSYNC); /* Make sure that this is a valid invocation of the clone. * Perhaps unnecessary, given FDVERIFY, but what the heck... */ if(stat(tmpname,&statb) < 0 || statb.st_nlink != 1 || !S_ISREG(statb.st_mode)) error_exit(badexec); if(ruserid != euserid && ((statb.st_mode & S_ISUID) == 0 || statb.st_uid != euserid)) error_exit(badexec); goto exec; } /* Make sure that this is the real setuid program, not the clone. * It is possible by clever hacking to get past this point in the * clone, but it doesn't do the hacker any good that I can see. */ if(euserid) error_exit(badexec); #endif /* _lib_setreuid */ /* Open the script for reading first and then validate it. This * prevents someone from pulling a switcheroo while we are validating. */ n = open(p,0); if(n == FDIN) { n = dup(n); close(FDIN); } if(n < 0) error_exit(badopen); /* validate execution rights to this script */ if(fstat(FDIN,&statb) < 0 || (statb.st_mode & ~S_IFMT) != SPECIAL) euserid = ruserid; else euserid = statb.st_uid; /* do it the easy way if you can */ if(euserid == ruserid && egroupid == rgroupid) { if(access(p,X_OK) < 0) error_exit(badexec); } else { /* have to check access on each component */ while(*p++) { if(*p == '/' || *p == 0) { m = *p; *p = 0; if(eaccess(argv[0],X_OK) < 0) error_exit(badexec); *p = m; } } p = argv[0]; } if(fstat(n, &statb) < 0 || !S_ISREG(statb.st_mode)) error_exit(badopen); if(stat(p, &statx) < 0 || statb.st_ino != statx.st_ino || statb.st_dev != statx.st_dev) error_exit(badexec); if(stat(THISPROG, &statx) < 0 || (statb.st_ino == statx.st_ino && statb.st_dev == statx.st_dev)) error_exit(badexec); close(FDIN); if(fcntl(n,F_DUPFD,FDIN) != FDIN) error_exit(badexec); close(n); /* compute the desired new effective user and group id */ effuid = euserid; effgid = egroupid; mode = 0; if(statb.st_mode & S_ISUID) effuid = statb.st_uid; if(statb.st_mode & S_ISGID) effgid = statb.st_gid; /* see if group needs setting */ if(effgid != egroupid) if(effgid != rgroupid || setgid(rgroupid) < 0) mode = S_ISGID; /* now see if the uid needs setting */ if(mode) { if(effuid != ruserid) mode |= S_ISUID; } else if(effuid) { if(effuid != ruserid || setuid(ruserid) < 0) mode = S_ISUID; } if(mode) setids(mode, effuid, effgid); #ifndef _lib_setreuid exec: #endif /* _lib_setreuid */ /* only use SHELL if file is in trusted directory and ends in sh */ shell = getenv("SHELL"); if(shell == 0 || !endsh(shell) || ( !in_dir("/bin",shell) && !in_dir("/usr/bin",shell) && !in_dir("/usr/lbin",shell) && !in_dir("/usr/local/bin",shell))) shell = DEFSHELL; argv[0] = command; argv[1] = (char*)devfd; execv(shell,argv); error_exit(badexec); }
/* * Save all of the undetermined messages at the top of "mbox" * Save all untouched messages back in the system mailbox. * Remove the system mailbox, if none saved there. */ void quit() { int mcount, p, modify, autohold, anystat, holdbit, nohold; long lp; FILE *ibuf = NULL, *obuf, *fbuf, *rbuf = NULL, *readstat; register struct message *mp; register int c; extern char tempQuit[], tempResid[]; struct stat minfo; char *id; /* * If we are read only, we can't do anything, * so just return quickly. */ if (readonly) return; /* * See if there any messages to save in mbox. If no, we * can save copying mbox to /tmp and back. * * Check also to see if any files need to be preserved. * Delete all untouched messages to keep them out of mbox. * If all the messages are to be preserved, just exit with * a message. * * If the luser has sent mail to himself, refuse to do * anything with the mailbox, unless mail locking works. */ lock(mailname); #ifndef CANLOCK if (selfsent) { printf(ediag("You have new mail.\n", "u WAS ESTX NOWAQ PO^TA.\n")); unlock(); return; } #endif ibuf = rbuf = NULL; if (stat(mailname, &minfo) >= 0 && minfo.st_size > mailsize) { printf(ediag( "New mail has arrived.\n", "pRI[LA NOWAQ PO^TA.\n")); #ifdef MSDOS maketemp(tempResid); #endif if ( fclear(tempResid) < 0 || (rbuf = TmpOpen(tempResid, "a+")) == NULL ) { perror(tempResid); remove(tempResid); } fbuf = fopen(mailname, "r"); if (rbuf == NULL || fbuf == NULL) goto newmail; #ifdef APPEND fseek(fbuf, mailsize, 0); while ((c = getc(fbuf)) != EOF) putc(c, rbuf); #else lp = minfo.st_size - mailsize; while (lp-- > 0) { c = getc(fbuf); if (c == EOF) goto newmail; putc(c, rbuf); } #endif fclose(fbuf); } /* * Adjust the message flags in each message. */ anystat = 0; autohold = value("hold") != NOSTR; holdbit = autohold ? MPRESERVE : MBOX; nohold = MBOX|MSAVED|MDELETED|MPRESERVE; if (value("keepsave") != NOSTR) nohold &= ~MSAVED; for (mp = &message[0]; mp < &message[msgCount]; mp++) { if (mp->m_flag & MNEW) { mp->m_flag &= ~MNEW; mp->m_flag |= MSTATUS; } if (mp->m_flag & MSTATUS) anystat++; if ((mp->m_flag & MTOUCH) == 0) mp->m_flag |= MPRESERVE; if ((mp->m_flag & nohold) == 0) mp->m_flag |= holdbit; } modify = 0; if (Tflag != NOSTR) { if ((readstat = fopen(Tflag, "w")) == NULL) Tflag = NOSTR; } for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) { if (mp->m_flag & MBOX) c++; if (mp->m_flag & MPRESERVE) p++; if (mp->m_flag & MODIFY) modify++; if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { id = hfield("article-id", mp); if (id != NOSTR) fprintf(readstat, "%s\n", id); } } if (Tflag != NOSTR) fclose(readstat); if (p == msgCount && !modify && !anystat) { if (p == 1) printf(ediag( "Held 1 message in %s\n", "1 SOOB]ENIE OSTAETSQ W %s\n"), mailname); else if (p > 0) printf(ediag( "Held %d messages in %s\n", "%d SOOB]ENIJ OSTA@TSQ W %s\n"), p, mailname); TmpDel(rbuf); unlock(); return; } if (c == 0) { if (p != 0) { writeback(rbuf); unlock(); return; } goto cream; } /* * Create another temporary file and copy user's mbox file * darin. If there is no mbox, copy nothing. * If he has specified "append" don't copy his mailbox, * just copy saveable entries at the end. */ mcount = c; if (value("append") == NOSTR) { #ifdef MSDOS maketemp(tempQuit); #endif if ( fclear(tempQuit) < 0 || (ibuf = TmpOpen(tempQuit, "a+")) == NULL ) { perror(tempQuit); remove(tempQuit); TmpDel(rbuf); unlock(); return; } if ((fbuf = fopen(mbox, "r")) != NULL) { while ((c = getc(fbuf)) != EOF) putc(c, ibuf); fclose(fbuf); } if (ferror(ibuf)) { ioerror(tempQuit, 1); TmpDel(ibuf); TmpDel(rbuf); unlock(); return; } if ( fclear(mbox) < 0 || (obuf = fopen(mbox, "a")) == NULL ) { perror(mbox); remove(mbox); TmpDel(ibuf); TmpDel(rbuf); unlock(); return; } } else if ((obuf = fopen(mbox, "a")) == NULL) { perror(mbox); TmpDel(rbuf); unlock(); return; } for (mp = &message[0]; mp < &message[msgCount]; mp++) if (mp->m_flag & MBOX) if (send(mp, obuf, 0) < 0) { ioerror(mbox, 1); fclose(obuf); TmpDel(ibuf); TmpDel(rbuf); unlock(); return; } /* * Copy the user's old mbox contents back * to the end of the stuff we just saved. * If we are appending, this is unnecessary. */ if (value("append") == NOSTR) { rewind(ibuf); while ((c = getc(ibuf)) != EOF) { putc(c, obuf); if (ferror(obuf)) goto Oerr; } TmpDel(ibuf); ibuf = NULL; fflush(obuf); } if (ferror(obuf)) { Oerr: ioerror(mbox, 1); fclose(obuf); TmpDel(ibuf); TmpDel(rbuf); unlock(); return; } fclose(obuf); if (mcount == 1) printf(ediag( "Saved 1 message in mbox\n", "1 SOOB]ENIE ZAPISYWAETSQ W mbox\n")); else if (mcount > 0) printf(ediag( "Saved %d messages in mbox\n", "%d SOOB]ENIJ ZAPISYWA@TSQ W mbox\n"), mcount); /* * Now we are ready to copy back preserved files to * the system mailbox, if any were requested. */ if (p != 0) { writeback(rbuf); unlock(); return; } /* * Finally, remove his /usr/mail file. * If new mail has arrived, copy it back. */ cream: if (rbuf != NULL) { if ( fclear(mailname) < 0 || (fbuf = fopen(mailname, "a")) == NULL ) goto newmail; rewind(rbuf); while ((c = getc(rbuf)) != EOF) putc(c, fbuf); fclose(fbuf); TmpDel(rbuf); alter(mailname); unlock(); return; } demail(); unlock(); return; newmail: printf(ediag("Thou hast new mail.\n","wAM ESTX NOWAQ PO^TA.\n")); TmpDel(rbuf); TmpDel(ibuf); unlock(); return; }