Beispiel #1
0
int
auth_finalize(void)
{
    char temp_name[1024];	/* large filename size */

    if (xauth_modified) {
	if (dieing) {
	    if (verbose) {
		/*
		 * called from a signal handler -- printf is *not* reentrant; also
		 * fileno() might not be reentrant, avoid it if possible, and use
		 * stderr instead of stdout
		 */
#ifdef STDERR_FILENO
		WRITES(STDERR_FILENO, "\nAborting changes to authority file ");
		WRITES(STDERR_FILENO, xauth_filename);
		WRITES(STDERR_FILENO, "\n");
#else
		WRITES(fileno(stderr), "\nAborting changes to authority file ");
		WRITES(fileno(stderr), xauth_filename);
		WRITES(fileno(stderr), "\n");
#endif
	    }
	} else if (!xauth_allowed) {
	    fprintf (stderr,
		     "%s:  %s not writable, changes ignored\n",
		     ProgramName, xauth_filename);
	} else {
	    if (verbose) {
		printf ("%s authority file %s\n",
			ignore_locks ? "Ignoring locks and writing" :
			"Writing", xauth_filename);
	    }
	    temp_name[0] = '\0';
	    if (write_auth_file (temp_name) == -1) {
		fprintf (stderr,
			 "%s:  unable to write authority file %s\n",
			 ProgramName, temp_name);
	    } else {
		(void) unlink (xauth_filename);
#if defined(WIN32) || defined(__UNIXOS2__)
		if (rename(temp_name, xauth_filename) == -1)
#else
		/* Attempt to rename() if link() fails, since this may be on a FS that does not support hard links */
		if (link (temp_name, xauth_filename) == -1 && rename(temp_name, xauth_filename) == -1)
#endif
		{
		    fprintf (stderr,
		     "%s:  unable to link authority file %s, use %s\n",
			     ProgramName, xauth_filename, temp_name);
		} else {
		    (void) unlink (temp_name);
		}
	    }
	}
    }

    if (xauth_locked) {
	XauUnlockAuth (xauth_filename);
    }
    (void) umask (original_umask);
    return 0;
}
Beispiel #2
0
Datei: send.c Projekt: dscho/nmh
int
main (int argc, char **argv)
{
    int msgp = 0, distsw = 0, vecp;
    int isdf = 0, mime = 0;
    int msgnum, status;
    char *cp, *dfolder = NULL, *maildir = NULL;
    char buf[BUFSIZ], **ap, **argp, **arguments, *program;
    char *msgs[MAXARGS], **vec;
    struct msgs *mp;
    struct stat st;

    if (nmh_init(argv[0], 1)) { return 1; }

    arguments = getarguments (invo_name, argc, argv, 1);
    argp = arguments;

    vec = argsplit(postproc, &program, &vecp);

    vec[vecp++] = "-library";
    vec[vecp++] = getcpy (m_maildir (""));

    if ((cp = context_find ("fileproc"))) {
	vec[vecp++] = "-fileproc";
	vec[vecp++] = cp;
    }

    if ((cp = context_find ("mhlproc"))) {
	vec[vecp++] = "-mhlproc";
	vec[vecp++] = cp;
    }

    if ((cp = context_find ("credentials"))) {
	/* post doesn't read context so need to pass credentials. */
	vec[vecp++] = "-credentials";
	vec[vecp++] = cp;
    }

    while ((cp = *argp++)) {
	if (*cp == '-') {
	    switch (smatch (++cp, switches)) {
		case AMBIGSW: 
		    ambigsw (cp, switches);
		    done (1);
		case UNKWNSW: 
		    adios (NULL, "-%s unknown\n", cp);

		case HELPSW: 
		    snprintf (buf, sizeof(buf), "%s [file] [switches]", invo_name);
		    print_help (buf, switches, 1);
		    done (0);
		case VERSIONSW:
		    print_version(invo_name);
		    done (0);

		case DRAFTSW: 
		    msgs[msgp++] = draft;
		    continue;

		case DFOLDSW: 
		    if (dfolder)
			adios (NULL, "only one draft folder at a time!");
		    if (!(cp = *argp++) || *cp == '-')
			adios (NULL, "missing argument to %s", argp[-2]);
		    dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
			    *cp != '@' ? TFOLDER : TSUBCWF);
		    continue;
		case DMSGSW: 
		    if (!(cp = *argp++) || *cp == '-')
			adios (NULL, "missing argument to %s", argp[-2]);
		    msgs[msgp++] = cp;
		    continue;
		case NDFLDSW: 
		    dfolder = NULL;
		    isdf = NOTOK;
		    continue;

		case PUSHSW: 
		    pushsw++;
		    continue;
		case NPUSHSW: 
		    pushsw = 0;
		    continue;

		case SPLITSW: 
		    if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1)
			adios (NULL, "missing argument to %s", argp[-2]);
		    continue;

		case UNIQSW: 
		    unique++;
		    continue;
		case NUNIQSW: 
		    unique = 0;
		    continue;

		case FORWSW:
		    forwsw++;
		    continue;
		case NFORWSW:
		    forwsw = 0;
		    continue;

		case VERBSW: 
		    verbsw++;
		    vec[vecp++] = --cp;
		    continue;
		case NVERBSW:
		    verbsw = 0;
		    vec[vecp++] = --cp;
		    continue;

		case MIMESW:
		    mime++;
		    vec[vecp++] = --cp;
		    continue;
		case NMIMESW:
		    mime = 0;
		    vec[vecp++] = --cp;
		    continue;

		case DEBUGSW: 
		    debugsw++;	/* fall */
		case NFILTSW: 
		case FRMTSW: 
		case NFRMTSW: 
		case BITSTUFFSW:
		case NBITSTUFFSW:
		case MSGDSW: 
		case NMSGDSW: 
		case WATCSW: 
		case NWATCSW: 
		case SNOOPSW: 
		case SASLSW:
		case NOSASLSW:
		case TLSSW:
		case INITTLSSW:
		case NTLSSW:
		    vec[vecp++] = --cp;
		    continue;

		case ALIASW: 
		case FILTSW: 
		case WIDTHSW: 
		case CLIESW: 
		case SERVSW: 
		case SASLMECHSW:
		case SASLMXSSFSW:
		case USERSW:
		case PORTSW:
		case MTSSW:
		case MESSAGEIDSW:
		    vec[vecp++] = --cp;
		    if (!(cp = *argp++) || *cp == '-')
			adios (NULL, "missing argument to %s", argp[-2]);
		    vec[vecp++] = cp;
		    continue;
		
		case ATTACHSW:
		    advise(NULL, "The -attach switch is deprecated");
		    continue;
		case NOATTACHSW:
		    advise(NULL, "The -noattach switch is deprecated");
		    continue;

		case ATTACHFORMATSW:
		    advise(NULL, "The -attachformat switch is deprecated");
		    continue;
	    }
	} else {
	    msgs[msgp++] = cp;
	}
    }

    /*
     * check for "Aliasfile:" profile entry
     */
    if ((cp = context_find ("Aliasfile"))) {
	char *dp = NULL;

	for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++) {
	    vec[vecp++] = "-alias";
	    vec[vecp++] = *ap;
	}
    }

    if (dfolder == NULL) {
	if (msgp == 0) {
	    msgs[msgp++] = getcpy (m_draft (NULL, NULL, 1, &isdf));
	    if (stat (msgs[0], &st) == NOTOK)
		adios (msgs[0], "unable to stat draft file");
	    cp = concat ("Use \"", msgs[0], "\"? ", NULL);
	    for (status = LISTDSW; status != YESW;) {
		if (!(argp = getans (cp, anyl)))
		    done (1);
		switch (status = smatch (*argp, anyl)) {
		    case NOSW: 
			done (0);
		    case YESW: 
			break;
		    case LISTDSW: 
			showfile (++argp, msgs[0]);
			break;
		    default:
			advise (NULL, "say what?");
			break;
		}
	    }
	} else {
	    for (msgnum = 0; msgnum < msgp; msgnum++)
		msgs[msgnum] = getcpy (m_maildir (msgs[msgnum]));
	}
    } else {
	if (!context_find ("path"))
	    free (path ("./", TFOLDER));

	if (!msgp)
	    msgs[msgp++] = "cur";
	maildir = m_maildir (dfolder);

	if (chdir (maildir) == NOTOK)
	    adios (maildir, "unable to change directory to");

	/* read folder and create message structure */
	if (!(mp = folder_read (dfolder, 1)))
	    adios (NULL, "unable to read folder %s", dfolder);

	/* check for empty folder */
	if (mp->nummsg == 0)
	    adios (NULL, "no messages in %s", dfolder);

	/* parse all the message ranges/sequences and set SELECTED */
	for (msgnum = 0; msgnum < msgp; msgnum++)
	    if (!m_convert (mp, msgs[msgnum]))
		done (1);
	seq_setprev (mp);	/* set the previous-sequence */

	for (msgp = 0, msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
	    if (is_selected (mp, msgnum)) {
		msgs[msgp++] = getcpy (m_name (msgnum));
		unset_exists (mp, msgnum);
	    }
	}

	mp->msgflags |= SEQMOD;
	seq_save (mp);
    }

#ifdef WHATNOW
go_to_it:
#endif /* WHATNOW */

    if ((cp = getenv ("SIGNATURE")) == NULL || *cp == 0)
	if ((cp = context_find ("signature")) && *cp)
	    m_putenv ("SIGNATURE", cp);

    for (msgnum = 0; msgnum < msgp; msgnum++)
	if (stat (msgs[msgnum], &st) == NOTOK)
	    adios (msgs[msgnum], "unable to stat draft file");

    if ((annotext = getenv ("mhannotate")) == NULL || *annotext == 0)
	annotext = NULL;
    if (annotext && ((cp = getenv ("mhinplace")) != NULL && *cp != 0))
	inplace = atoi (cp);
    if ((altmsg = getenv ("mhaltmsg")) == NULL || *altmsg == 0)
	altmsg = NULL;	/* used by dist interface - see below */

    if ((cp = getenv ("mhdist"))
	    && *cp
	    && (distsw = atoi (cp))
	    && altmsg) {
	vec[vecp++] = "-dist";
	if ((cp = m_mktemp2(altmsg, invo_name, NULL, NULL)) == NULL) {
	    adios(NULL, "unable to create temporary file in %s",
		  get_temp_dir());
	}
	distfile = getcpy (cp);
	(void) m_unlink(distfile);
	if (link (altmsg, distfile) == NOTOK) {
	    /* Cygwin with FAT32 filesystem produces EPERM. */
	    if (errno != EXDEV  &&  errno != EPERM
#ifdef EISREMOTE
		    && errno != EISREMOTE
#endif /* EISREMOTE */
		)
		adios (distfile, "unable to link %s to", altmsg);
	    free (distfile);
	    if ((cp = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) {
		adios(NULL, "unable to create temporary file in %s",
		      get_temp_dir());
	    }
	    distfile = getcpy (cp);
	    {
		int in, out;
		struct stat st;

		if ((in = open (altmsg, O_RDONLY)) == NOTOK)
		    adios (altmsg, "unable to open");
		fstat(in, &st);
		if ((out = creat (distfile, (int) st.st_mode & 0777)) == NOTOK)
		    adios (distfile, "unable to write");
		cpydata (in, out, altmsg, distfile);
		close (in);
		close (out);
	    }	
	}
    } else {
	distfile = NULL;
    }

    if (altmsg == NULL || stat (altmsg, &st) == NOTOK) {
	st.st_mtime = 0;
	st.st_dev = 0;
	st.st_ino = 0;
    }
    if (pushsw)
	push ();

    status = 0;
    closefds (3);

    for (msgnum = 0; msgnum < msgp; msgnum++) {
	switch (sendsbr (vec, vecp, program, msgs[msgnum], &st, 1)) {
	    case DONE: 
		done (++status);
	    case NOTOK: 
		status++;	/* fall */
	    case OK:
		break;
	}
    }

    context_save ();	/* save the context file */
    done (status);
    return 1;
}
Beispiel #3
0
void JIT::compileOpCallSlowCase(Instruction* instruction, unsigned i, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID)
{
    int dst = instruction[1].u.operand;
    int callee = instruction[2].u.operand;
    int argCount = instruction[3].u.operand;
    int registerOffset = instruction[4].u.operand;

    __ link(iter->from, __ label());

    // The arguments have been set up on the hot path for op_call_eval
    if (opcodeID == op_call)
        compileOpCallSetupArgs(instruction);
    else if (opcodeID == op_construct)
        compileOpConstructSetupArgs(instruction);

    // Fast check for JS function.
    __ testl_i32r(JSImmediate::TagMask, X86::ecx);
    JmpSrc callLinkFailNotObject = __ jne();
    __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), X86::ecx);
    JmpSrc callLinkFailNotJSFunction = __ jne();

    // First, in the case of a construct, allocate the new object.
    if (opcodeID == op_construct) {
        emitCTICall(i, Interpreter::cti_op_construct_JSConstruct);
        emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
        emitGetVirtualRegister(callee, X86::ecx, i);
    }

    __ movl_i32r(argCount, X86::edx);

    // Speculatively roll the callframe, assuming argCount will match the arity.
    __ movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi);
    __ addl_i32r(registerOffset * static_cast<int>(sizeof(Register)), X86::edi);

    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation =
        emitNakedCall(i, m_interpreter->m_ctiVirtualCallPreLink);

    JmpSrc storeResultForFirstRun = __ jmp();

    // This is the address for the cold path *after* the first run (which tries to link the call).
    m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther = __ label();

    // The arguments have been set up on the hot path for op_call_eval
    if (opcodeID == op_call)
        compileOpCallSetupArgs(instruction);
    else if (opcodeID == op_construct)
        compileOpConstructSetupArgs(instruction);

    // Check for JSFunctions.
    __ testl_i32r(JSImmediate::TagMask, X86::ecx);
    JmpSrc isNotObject = __ jne();
    __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), X86::ecx);
    JmpSrc isJSFunction = __ je();

    // This handles host functions
    JmpDst notJSFunctionlabel = __ label();
    __ link(isNotObject, notJSFunctionlabel);
    __ link(callLinkFailNotObject, notJSFunctionlabel);
    __ link(callLinkFailNotJSFunction, notJSFunctionlabel);
    emitCTICall(i, ((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction));
    JmpSrc wasNotJSFunction = __ jmp();

    // Next, handle JSFunctions...
    __ link(isJSFunction, __ label());

    // First, in the case of a construct, allocate the new object.
    if (opcodeID == op_construct) {
        emitCTICall(i, Interpreter::cti_op_construct_JSConstruct);
        emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
        emitGetVirtualRegister(callee, X86::ecx, i);
    }

    // Speculatively roll the callframe, assuming argCount will match the arity.
    __ movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi);
    __ addl_i32r(registerOffset * static_cast<int>(sizeof(Register)), X86::edi);
    __ movl_i32r(argCount, X86::edx);

    emitNakedCall(i, m_interpreter->m_ctiVirtualCall);

    // Put the return value in dst. In the interpreter, op_ret does this.
    JmpDst storeResult = __ label();
    __ link(wasNotJSFunction, storeResult);
    __ link(storeResultForFirstRun, storeResult);
    emitPutVirtualRegister(dst);

#if ENABLE(CODEBLOCK_SAMPLING)
    __ movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_interpreter->sampler()->codeBlockSlot());
#endif
}
Beispiel #4
0
int
copy_file(FTSENT *entp, int dne)
{
	static char buf[MAXBSIZE];
	struct stat to_stat, *fs;
	int ch, checkch, from_fd, rcount, rval, to_fd, tolnk, wcount;
	char *p;
	size_t ptotal = 0;
	
	if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
		warn("%s", entp->fts_path);
		return (1);
	}

	to_fd = -1;
	fs = entp->fts_statp;
	tolnk = ((Rflag && !(Lflag || Hflag)) || Pflag);

	/*
	 * If the file exists and we're interactive, verify with the user.
	 * If the file DNE, set the mode to be the from file, minus setuid
	 * bits, modified by the umask; arguably wrong, but it makes copying
	 * executables work right and it's been that way forever.  (The
	 * other choice is 666 or'ed with the execute bits on the from file
	 * modified by the umask.)
	 */
	if (!dne) {
		struct stat sb;
		int sval;

		if (iflag) {
			(void)fprintf(stderr, "overwrite %s? ", to.p_path);
			checkch = ch = getchar();
			while (ch != '\n' && ch != EOF)
				ch = getchar();
			if (checkch != 'y' && checkch != 'Y') {
				(void)close(from_fd);
				return (0);
			}
		}

		sval = tolnk ?
			lstat(to.p_path, &sb) : stat(to.p_path, &sb);
		if (sval == -1) {
			warn("stat: %s", to.p_path);
			(void)close(from_fd);
			return (1);
		}

		if (!(tolnk && S_ISLNK(sb.st_mode)))
			to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
	} else
		to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
		    fs->st_mode & ~(S_ISUID | S_ISGID));

	if (to_fd == -1 && (fflag || tolnk)) {
		/*
		 * attempt to remove existing destination file name and
		 * create a new file
		 */
		(void)unlink(to.p_path);
		to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
			     fs->st_mode & ~(S_ISUID | S_ISGID));
	}

	if (to_fd == -1) {
		warn("%s", to.p_path);
		(void)close(from_fd);
		return (1);
	}

	rval = 0;

	/* if hard linking then simply close the open fds, link and return */
	if (lflag) {
		(void)close(from_fd);
		(void)close(to_fd);
		(void)unlink(to.p_path);
		if (link(entp->fts_path, to.p_path)) {
			warn("%s", to.p_path);
			return (1);
		}
		return (0);
	}

	/*
	 * There's no reason to do anything other than close the file
	 * now if it's empty, so let's not bother.
	 */
	if (fs->st_size > 0) {
		struct finfo fi;

		fi.from = entp->fts_path;
		fi.to = to.p_path;
		fi.size = (size_t)fs->st_size;

		/*
		 * Mmap and write if less than 8M (the limit is so
		 * we don't totally trash memory on big files).
		 * This is really a minor hack, but it wins some CPU back.
		 */
		bool use_read;

		use_read = true;
		if (fs->st_size <= MMAP_MAX_SIZE) {
			size_t fsize = (size_t)fs->st_size;
			p = mmap(NULL, fsize, PROT_READ, MAP_FILE|MAP_SHARED,
			    from_fd, (off_t)0);
			if (p != MAP_FAILED) {
				size_t remainder;

				use_read = false;

				(void) madvise(p, (size_t)fs->st_size,
				     MADV_SEQUENTIAL);

				/*
				 * Write out the data in small chunks to
				 * avoid locking the output file for a
				 * long time if the reading the data from
				 * the source is slow.
				 */
				remainder = fsize;
				do {
					ssize_t chunk;

					chunk = (remainder > MMAP_MAX_WRITE) ?
					    MMAP_MAX_WRITE : remainder;
					if (write(to_fd, &p[fsize - remainder],
					    chunk) != chunk) {
						warn("%s", to.p_path);
						rval = 1;
						break;
					}
					remainder -= chunk;
					ptotal += chunk;
					if (pinfo)
						progress(&fi, ptotal);
				} while (remainder > 0);

				if (munmap(p, fsize) < 0) {
					warn("%s", entp->fts_path);
					rval = 1;
				}
			}
		}

		if (use_read) {
			while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
				wcount = write(to_fd, buf, (size_t)rcount);
				if (rcount != wcount || wcount == -1) {
					warn("%s", to.p_path);
					rval = 1;
					break;
				}
				ptotal += wcount;
				if (pinfo)
					progress(&fi, ptotal);
			}
			if (rcount < 0) {
				warn("%s", entp->fts_path);
				rval = 1;
			}
		}
	}

#if HAVE_FUNC2_FCPXATTR_SYS_EXTATTR_H
	if (pflag && (fcpxattr(from_fd, to_fd) != 0))
		warn("%s: error copying extended attributes", to.p_path);
#endif

	(void)close(from_fd);

	if (rval == 1) {
		(void)close(to_fd);
		return (1);
	}

	if (pflag && setfile(fs, to_fd))
		rval = 1;
	/*
	 * If the source was setuid or setgid, lose the bits unless the
	 * copy is owned by the same user and group.
	 */
#define	RETAINBITS \
	(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
	if (!pflag && dne
	    && fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) {
		if (fstat(to_fd, &to_stat)) {
			warn("%s", to.p_path);
			rval = 1;
		} else if (fs->st_gid == to_stat.st_gid &&
		    fchmod(to_fd, fs->st_mode & RETAINBITS & ~myumask)) {
			warn("%s", to.p_path);
			rval = 1;
		}
	}
	if (close(to_fd)) {
		warn("%s", to.p_path);
		rval = 1;
	}
	/* set the mod/access times now after close of the fd */
	if (pflag && set_utimes(to.p_path, fs)) { 
	    rval = 1;
	}
	return (rval);
}
Beispiel #5
0
int
copy_file(const FTSENT *entp, int dne)
{
	static char *buf = NULL;
	static size_t bufsize;
	struct stat *fs;
	ssize_t wcount;
	size_t wresid;
	off_t wtotal;
	int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0;
	char *bufp;
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
	char *p;
#endif

	if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
		warn("%s", entp->fts_path);
		return (1);
	}

	fs = entp->fts_statp;

	/*
	 * If the file exists and we're interactive, verify with the user.
	 * If the file DNE, set the mode to be the from file, minus setuid
	 * bits, modified by the umask; arguably wrong, but it makes copying
	 * executables work right and it's been that way forever.  (The
	 * other choice is 666 or'ed with the execute bits on the from file
	 * modified by the umask.)
	 */
	if (!dne) {
#define YESNO "(y/n [n]) "
		if (nflag) {
			if (vflag)
				printf("%s not overwritten\n", to.p_path);
			(void)close(from_fd);
			return (0);
		} else if (iflag) {
			(void)fprintf(stderr, "overwrite %s? %s", 
					to.p_path, YESNO);
			checkch = ch = getchar();
			while (ch != '\n' && ch != EOF)
				ch = getchar();
			if (checkch != 'y' && checkch != 'Y') {
				(void)close(from_fd);
				(void)fprintf(stderr, "not overwritten\n");
				return (1);
			}
		}
		
		if (fflag) {
		    /* remove existing destination file name, 
		     * create a new file  */
		    (void)unlink(to.p_path);
				if (!lflag)
		    	to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
				  fs->st_mode & ~(S_ISUID | S_ISGID));
		} else {
				if (!lflag)
		    	/* overwrite existing destination file name */
		    	to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
		}
	} else {
		if (!lflag)
			to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
		  fs->st_mode & ~(S_ISUID | S_ISGID));
	}
	
	if (to_fd == -1) {
		warn("%s", to.p_path);
		(void)close(from_fd);
		return (1);
	}

	rval = 0;

	if (!lflag) {
		/*
		 * Mmap and write if less than 8M (the limit is so we don't totally
		 * trash memory on big files.  This is really a minor hack, but it
		 * wins some CPU back.
		 * Some filesystems, such as smbnetfs, don't support mmap,
		 * so this is a best-effort attempt.
		 */
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
		if (S_ISREG(fs->st_mode) && fs->st_size > 0 &&
	    	    fs->st_size <= 8 * 1024 * 1024 &&
		    (p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
		    MAP_SHARED, from_fd, (off_t)0)) != MAP_FAILED) {
			wtotal = 0;
			for (bufp = p, wresid = fs->st_size; ;
			bufp += wcount, wresid -= (size_t)wcount) {
				wcount = write(to_fd, bufp, wresid);
				if (wcount <= 0)
					break;
				wtotal += wcount;
				if (info) {
					info = 0;
					(void)fprintf(stderr,
					    "%s -> %s %3d%%\n",
					    entp->fts_path, to.p_path,
					    cp_pct(wtotal, fs->st_size));
				}
				if (wcount >= (ssize_t)wresid)
					break;
			}
			if (wcount != (ssize_t)wresid) {
				warn("%s", to.p_path);
				rval = 1;
			}
			/* Some systems don't unmap on close(2). */
			if (munmap(p, fs->st_size) < 0) {
				warn("%s", entp->fts_path);
				rval = 1;
			}
		} else
#endif
		{
			if (buf == NULL) {
				/*
				 * Note that buf and bufsize are static. If
				 * malloc() fails, it will fail at the start
				 * and not copy only some files. 
				 */ 
				if (sysconf(_SC_PHYS_PAGES) > 
				    PHYSPAGES_THRESHOLD)
					bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
				else
					bufsize = BUFSIZE_SMALL;
				buf = malloc(bufsize);
				if (buf == NULL)
					err(1, "Not enough memory");
			}
			wtotal = 0;
			while ((rcount = read(from_fd, buf, bufsize)) > 0) {
				for (bufp = buf, wresid = rcount; ;
			    	bufp += wcount, wresid -= wcount) {
					wcount = write(to_fd, bufp, wresid);
					if (wcount <= 0)
						break;
					wtotal += wcount;
					if (info) {
						info = 0;
						(void)fprintf(stderr,
						    "%s -> %s %3d%%\n",
						    entp->fts_path, to.p_path,
						    cp_pct(wtotal, fs->st_size));
					}
					if (wcount >= (ssize_t)wresid)
						break;
				}
				if (wcount != (ssize_t)wresid) {
					warn("%s", to.p_path);
					rval = 1;
					break;
				}
			}
			if (rcount < 0) {
				warn("%s", entp->fts_path);
				rval = 1;
			}
		}
	} else {
		if (link(entp->fts_path, to.p_path)) {
			warn("%s", to.p_path);
			rval = 1;
		}
	}
	
	/*
	 * Don't remove the target even after an error.  The target might
	 * not be a regular file, or its attributes might be important,
	 * or its contents might be irreplaceable.  It would only be safe
	 * to remove it if we created it and its length is 0.
	 */

	if (!lflag) {
		if (pflag && setfile(fs, to_fd))
			rval = 1;
		if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
			rval = 1;
		if (close(to_fd)) {
			warn("%s", to.p_path);
			rval = 1;
		}
	}

	(void)close(from_fd);

	return (rval);
}
Beispiel #6
0
int main(int argc, char *argv[])
{
	auth();
	printf("auth complete\n");

#ifdef WINDOWS_SYS
	// The current directory of the application is changed when using the native dialog on Windows
	// This is a quick fix until libretroshare is using a absolute path in the portable Version
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0)
	typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
	typedef QString (*_qt_filedialog_open_filename_hook)     (QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
	typedef QString (*_qt_filedialog_save_filename_hook)     (QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
	typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);

	extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook;
	extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook;
	extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook;
	extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook;

	qt_filedialog_open_filename_hook = filedialog_open_filename_hook;
	qt_filedialog_open_filenames_hook = filedialog_open_filenames_hook;
	qt_filedialog_save_filename_hook = filedialog_save_filename_hook;
	qt_filedialog_existing_directory_hook = filedialog_existing_directory_hook;
#else
	extern bool Q_GUI_EXPORT qt_use_native_dialogs;
	qt_use_native_dialogs = false;
#endif

	{
		/* Set the current directory to the application dir,
		   because the start dir with autostart from the registry run key is not the exe dir */
		QApplication app(argc, argv);
		QDir::setCurrent(QCoreApplication::applicationDirPath());
	}
#endif

	QStringList args = char_array_to_stringlist(argv+1, argc-1);

	Q_INIT_RESOURCE(images);

	// This is needed to allocate rsNotify, so that it can be used to ask for PGP passphrase
	//
	RsControl::earlyInitNotificationSystem() ;

	NotifyQt *notify = NotifyQt::Create();
	rsNotify->registerNotifyClient(notify);

	/* RetroShare Core Objects */
	RsInit::InitRsConfig();
	int initResult = RsInit::InitRetroShare(argc, argv);

	if(initResult == RS_INIT_NO_KEYRING)	// happens when we already have accounts, but no pgp key. This is when switching to the openpgp-sdk version.
	{
		QApplication dummyApp (argc, argv); // needed for QMessageBox
		/* Translate into the desired language */
		LanguageSupport::translate(LanguageSupport::defaultLanguageCode());

		QMessageBox msgBox;
		msgBox.setText(QObject::tr("This version of RetroShare is using OpenPGP-SDK. As a side effect, it's not using the system shared PGP keyring, but has it's own keyring shared by all RetroShare instances. <br><br>You do not appear to have such a keyring, although PGP keys are mentioned by existing RetroShare accounts, probably because you just changed to this new version of the software."));
		msgBox.setInformativeText(QObject::tr("Choose between:<br><ul><li><b>Ok</b> to copy the existing keyring from gnupg (safest bet), or </li><li><b>Close without saving</b> to start fresh with an empty keyring (you will be asked to create a new PGP key to work with RetroShare, or import a previously saved pgp keypair). </li><li><b>Cancel</b> to quit and forge a keyring by yourself (needs some PGP skills)</li></ul>"));
		msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Discard | QMessageBox::Cancel);
		msgBox.setDefaultButton(QMessageBox::Ok);
		msgBox.setWindowIcon(QIcon(":/images/rstray3.png"));

		int ret = msgBox.exec();

		if(ret == QMessageBox::Cancel)
			return 0 ;
		if(ret == QMessageBox::Ok)
		{
			if(!RsInit::copyGnuPGKeyrings())
				return 0 ;

			initResult = RsInit::InitRetroShare(argc, argv);

			displayWarningAboutDSAKeys() ;

		}
		else
			initResult = RS_INIT_OK ;
	}

	if (initResult < 0) {
		/* Error occured */
		QApplication dummyApp (argc, argv); // needed for QMessageBox
		/* Translate into the desired language */
		LanguageSupport::translate(LanguageSupport::defaultLanguageCode());

		displayWarningAboutDSAKeys();

		QMessageBox mb(QMessageBox::Critical, QObject::tr("RetroShare"), "", QMessageBox::Ok);
		mb.setWindowIcon(QIcon(":/images/rstray3.png"));

		switch (initResult)
		{
			case RS_INIT_AUTH_FAILED:
				std::cerr << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl;
				mb.setText(QObject::tr("Initialization failed. Wrong or missing installation of PGP."));
				break;
			default:
				/* Unexpected return code */
				std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl;
				mb.setText(QObject::tr("An unexpected error occurred. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult));
				break;
		}
		mb.exec();
		return 1;
	}

	/* create global settings object
	   path maybe wrong, when no profile exist
	   in this case it can be use only for default values */
	RshareSettings::Create ();

	/* Setup The GUI Stuff */
	Rshare rshare(args, argc, argv,
		QString::fromUtf8(RsInit::RsConfigDirectory().c_str()));

	std::string url = RsInit::getRetroShareLink();
	if (!url.empty()) {
		/* start with RetroShare link */
		EventReceiver eventReceiver;
		if (eventReceiver.sendRetroShareLink(QString::fromStdString(url))) {
			return 0;
		}

		/* Start RetroShare */
	}

	QSplashScreen splashScreen(QPixmap(":/images/splash.png")/* , Qt::WindowStaysOnTopHint*/);

	switch (initResult) {
	case RS_INIT_OK:
		{
			/* Login Dialog */
			/* check for existing Certificate */
			bool genCert = false;
			std::list<std::string> accountIds;
			if (RsInit::getAccountIds(accountIds) && (accountIds.size() > 0))
			{
				StartDialog sd;
				if (sd.exec() == QDialog::Rejected) {
					return 1;
				}

				/* if we're logged in */
				genCert = sd.requestedNewCert();
			}
			else
			{
				genCert = true;
			}

			if (genCert)
			{
				GenCertDialog gd(false);
				if (gd.exec () == QDialog::Rejected) {
					return 1;
				}
			}

			splashScreen.show();
		}
		break;
	case RS_INIT_HAVE_ACCOUNT:
		{
			splashScreen.show();
			splashScreen.showMessage(rshare.translate("SplashScreen", "Load profile"), Qt::AlignHCenter | Qt::AlignBottom);

			std::string preferredId;
			RsInit::getPreferedAccountId(preferredId);

			// true: note auto-login is active
			Rshare::loadCertificate(preferredId, true);
		}
		break;
	default:
		/* Unexpected return code */
		std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl;
		QMessageBox::warning(0, QObject::tr("RetroShare"), QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult));
		return 1;
	}

	/* recreate global settings object, now with correct path */
	RshareSettings::Create(true);
	Rshare::resetLanguageAndStyle();

	SoundManager::create();

	splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom);

	/* stop Retroshare if startup fails */
	if (!RsControl::instance()->StartupRetroShare())
	{
		std::cerr << "libretroshare failed to startup!" << std::endl;
		return 1;
	}


	Rshare::initPlugins();

	splashScreen.showMessage(rshare.translate("SplashScreen", "Create interface"), Qt::AlignHCenter | Qt::AlignBottom);

	RsharePeerSettings::Create();

	Emoticons::load();

	if (Settings->value(QString::fromUtf8("FirstRun"), true).toBool()) {
		splashScreen.hide();

		Settings->setValue(QString::fromUtf8("FirstRun"), false);

#ifdef __APPLE__
		/* For OSX, we set the default to "cleanlooks", as the AQUA style hides some input boxes
		 * only on the first run - as the user might want to change it ;)
		 */
		QString osx_style("cleanlooks");
		Rshare::setStyle(osx_style);
		Settings->setInterfaceStyle(osx_style);
#endif

// This is now disabled - as it doesn't add very much.
// Need to make sure that defaults are sensible!
#ifdef ENABLE_QUICKSTART_WIZARD
		QuickStartWizard qstartWizard;
		qstartWizard.exec();
#endif

	}

	MainWindow *w = MainWindow::Create ();
	splashScreen.finish(w);

	EventReceiver *eventReceiver = NULL;
	if (Settings->getRetroShareProtocol()) {
		/* Create event receiver */
		eventReceiver = new EventReceiver;
		if (eventReceiver->start()) {
			QObject::connect(eventReceiver, SIGNAL(linkReceived(const QUrl&)), w, SLOT(retroshareLinkActivated(const QUrl&)));
		}
	}

	if (!url.empty()) {
		/* Now use link from the command line, because no RetroShare was running */
		RetroShareLink link(QString::fromStdString(url));
		if (link.valid()) {
			w->retroshareLinkActivated(link.toUrl());
		}
	}

	// I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to
	// avoid clashes between infos from threads.
	//

	qRegisterMetaType<FileDetail>("FileDetail") ;

	std::cerr << "connecting signals and slots" << std::endl ;
	QObject::connect(notify,SIGNAL(gotTurtleSearchResult(qulonglong,FileDetail)),w->transfersDialog->searchDialog	,SLOT(updateFiles(qulonglong,FileDetail))) ;
	QObject::connect(notify,SIGNAL(deferredSignatureHandlingRequested()),notify,SLOT(handleSignatureEvent()),Qt::QueuedConnection) ;
	QObject::connect(notify,SIGNAL(chatLobbyTimeShift(int)),notify,SLOT(handleChatLobbyTimeShift(int)),Qt::QueuedConnection) ;
	QObject::connect(notify,SIGNAL(diskFull(int,int))						,w                   		,SLOT(displayDiskSpaceWarning(int,int))) ;
	QObject::connect(notify,SIGNAL(filesPostModChanged(bool))         ,w                         ,SLOT(postModDirectories(bool)         )) ;
	QObject::connect(notify,SIGNAL(transfersChanged())                ,w->transfersDialog  		,SLOT(insertTransfers()                )) ;
	QObject::connect(notify,SIGNAL(publicChatChanged(int))            ,w->friendsDialog      		,SLOT(publicChatChanged(int)           ));
	QObject::connect(notify,SIGNAL(neighboursChanged())               ,w->friendsDialog->networkDialog    		,SLOT(securedUpdateDisplay())) ;
	QObject::connect(notify,SIGNAL(messagesChanged())                 ,w->messagesDialog   		,SLOT(insertMessages()                 )) ;
	QObject::connect(notify,SIGNAL(messagesTagsChanged())             ,w->messagesDialog   		,SLOT(messagesTagsChanged()            )) ;

	QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&,bool)),w->friendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool)));
	QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus()));

	QObject::connect(notify,SIGNAL(logInfoChanged(const QString&))		,w->friendsDialog->networkDialog,SLOT(setLogInfo(QString))) ;
	QObject::connect(notify,SIGNAL(discInfoChanged())						,w->friendsDialog->networkView,SLOT(update()),Qt::QueuedConnection) ;
	QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ;

	w->installGroupChatNotifier();

	/* only show window, if not startMinimized */
	if (RsInit::getStartMinimised() || Settings->getStartMinimized())
	{
		splashScreen.close();
	} else {
		w->show();
	}

	/* Startup a Timer to keep the gui's updated */
	QTimer *timer = new QTimer(w);
	timer -> connect(timer, SIGNAL(timeout()), notify, SLOT(UpdateGUI()));
	timer->start(1000);

	notify->enable() ;	// enable notification system after GUI creation, to avoid data races in Qt.

	/* dive into the endless loop */
	int ti = rshare.exec();
	delete w ;

	if (eventReceiver) {
		/* Destroy event receiver */
		delete eventReceiver;
		eventReceiver = NULL;
	}

	/* cleanup */
	ChatDialog::cleanupChat();
#ifdef RS_ENABLE_GXS
	RsGxsUpdateBroadcast::cleanup();
#endif

	RsControl::instance()->rsGlobalShutDown();

	delete(soundManager);
	soundManager = NULL;

	Settings->sync();
	delete(Settings);

	return ti ;
}
Beispiel #7
0
/* OS_GetLogLocation: v0.1, 2005/04/25 */
int OS_GetLogLocation(Eventinfo *lf)
{
    /* Checking what directories to create
     * Checking if the year directory is there.
     * If not, create it. Same for the month directory.
     */

    /* For the events */
    if(_eflog)
    {
        if(ftell(_eflog) == 0)
            unlink(__elogfile);
        fclose(_eflog);
        _eflog = NULL;
    }

    snprintf(__elogfile,OS_FLSIZE,"%s/%d/", EVENTS, lf->year);
    if(IsDir(__elogfile) == -1)
        if(mkdir(__elogfile,0770) == -1)
        {
            ErrorExit(MKDIR_ERROR,ARGV0,__elogfile);
        }

    snprintf(__elogfile,OS_FLSIZE,"%s/%d/%s", EVENTS, lf->year,lf->mon);

    if(IsDir(__elogfile) == -1)
        if(mkdir(__elogfile,0770) == -1)
        {
            ErrorExit(MKDIR_ERROR,ARGV0,__elogfile);
        }


    /* Creating the logfile name */
    snprintf(__elogfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log",
            EVENTS,
            lf->year,
            lf->mon,
            "archive",
            lf->day);


    _eflog = fopen(__elogfile,"a");
    if(!_eflog)
        ErrorExit("%s: Error opening logfile: '%s'",ARGV0,__elogfile);

    /* Creating a symlink */
    unlink(EVENTS_DAILY);

    if(link(__elogfile, EVENTS_DAILY) == -1)
    {
        ErrorExit(LINK_ERROR, ARGV0, __elogfile, EVENTS_DAILY);
    }


    /* for the alerts logs */
    if(_aflog)
    {
        if(ftell(_aflog) == 0)
            unlink(__alogfile);
        fclose(_aflog);
        _aflog = NULL;
    }

    snprintf(__alogfile,OS_FLSIZE,"%s/%d/", ALERTS, lf->year);
    if(IsDir(__alogfile) == -1)
        if(mkdir(__alogfile,0770) == -1)
        {
            ErrorExit(MKDIR_ERROR,ARGV0,__alogfile);
        }

    snprintf(__alogfile,OS_FLSIZE,"%s/%d/%s", ALERTS, lf->year,lf->mon);

    if(IsDir(__alogfile) == -1)
        if(mkdir(__alogfile,0770) == -1)
        {
            ErrorExit(MKDIR_ERROR,ARGV0,__alogfile);
        }


    /* Creating the logfile name */
    snprintf(__alogfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log",
            ALERTS,
            lf->year,
            lf->mon,
            "alerts",
            lf->day);

    _aflog = fopen(__alogfile,"a");

    if(!_aflog)
        ErrorExit("%s: Error opening logfile: '%s'",ARGV0,__alogfile);

    /* Creating a symlink */
    unlink(ALERTS_DAILY);

    if(link(__alogfile, ALERTS_DAILY) == -1)
    {
        ErrorExit(LINK_ERROR, ARGV0, __alogfile, ALERTS_DAILY);
    }


    /* For the firewall events */
    if(_fflog)
    {
        if(ftell(_fflog) == 0)
            unlink(__flogfile);
        fclose(_fflog);
        _fflog = NULL;
    }

    snprintf(__flogfile,OS_FLSIZE,"%s/%d/", FWLOGS, lf->year);
    if(IsDir(__flogfile) == -1)
        if(mkdir(__flogfile,0770) == -1)
        {
            ErrorExit(MKDIR_ERROR,ARGV0,__flogfile);
        }

    snprintf(__flogfile,OS_FLSIZE,"%s/%d/%s", FWLOGS, lf->year,lf->mon);

    if(IsDir(__flogfile) == -1)
        if(mkdir(__flogfile,0770) == -1)
        {
            ErrorExit(MKDIR_ERROR,ARGV0,__flogfile);
        }


    /* Creating the logfile name */
    snprintf(__flogfile,OS_FLSIZE,"%s/%d/%s/ossec-%s-%02d.log",
            FWLOGS,
            lf->year,
            lf->mon,
            "firewall",
            lf->day);

    _fflog = fopen(__flogfile,"a");

    if(!_fflog)
        ErrorExit("%s: Error opening logfile: '%s'",ARGV0,__flogfile);


    /* Creating a symlink */
    unlink(FWLOGS_DAILY);

    if(link(__flogfile, FWLOGS_DAILY) == -1)
    {
        ErrorExit(LINK_ERROR, ARGV0, __flogfile, FWLOGS_DAILY);
    }


    /* Setting the new day */
    __crt_day = lf->day;

    return(0);
}
Beispiel #8
0
Tcl_Obj *
TclpObjLink(
    Tcl_Obj *pathPtr,
    Tcl_Obj *toPtr,
    int linkAction)
{
    if (toPtr != NULL) {
        const char *src = Tcl_FSGetNativePath(pathPtr);
        const char *target = NULL;

        if (src == NULL) {
            return NULL;
        }

        /*
         * If we're making a symbolic link and the path is relative, then we
         * must check whether it exists _relative_ to the directory in which
         * the src is found (not relative to the current cwd which is just not
         * relevant in this case).
         *
         * If we're making a hard link, then a relative path is just converted
         * to absolute relative to the cwd.
         */

        if ((linkAction & TCL_CREATE_SYMBOLIC_LINK)
                && (Tcl_FSGetPathType(toPtr) == TCL_PATH_RELATIVE)) {
            Tcl_Obj *dirPtr, *absPtr;

            dirPtr = TclPathPart(NULL, pathPtr, TCL_PATH_DIRNAME);
            if (dirPtr == NULL) {
                return NULL;
            }
            absPtr = Tcl_FSJoinToPath(dirPtr, 1, &toPtr);
            Tcl_IncrRefCount(absPtr);
            if (Tcl_FSAccess(absPtr, F_OK) == -1) {
                Tcl_DecrRefCount(absPtr);
                Tcl_DecrRefCount(dirPtr);

                /*
                 * Target doesn't exist.
                 */

                errno = ENOENT;
                return NULL;
            }

            /*
             * Target exists; we'll construct the relative path we want below.
             */

            Tcl_DecrRefCount(absPtr);
            Tcl_DecrRefCount(dirPtr);
        } else {
            target = Tcl_FSGetNativePath(toPtr);
            if (target == NULL) {
                return NULL;
            }
            if (access(target, F_OK) == -1) {
                /*
                 * Target doesn't exist.
                 */

                errno = ENOENT;
                return NULL;
            }
        }

        if (access(src, F_OK) != -1) {
            /*
             * Src exists.
             */

            errno = EEXIST;
            return NULL;
        }

        /*
         * Check symbolic link flag first, since we prefer to create these.
         */

        if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
            int targetLen;
            Tcl_DString ds;
            Tcl_Obj *transPtr;

            /*
             * Now we don't want to link to the absolute, normalized path.
             * Relative links are quite acceptable (but links to ~user are not
             * -- these must be expanded first).
             */

            transPtr = Tcl_FSGetTranslatedPath(NULL, toPtr);
            if (transPtr == NULL) {
                return NULL;
            }
            target = Tcl_GetStringFromObj(transPtr, &targetLen);
            target = Tcl_UtfToExternalDString(NULL, target, targetLen, &ds);
            Tcl_DecrRefCount(transPtr);

            if (symlink(target, src) != 0) {
                toPtr = NULL;
            }
            Tcl_DStringFree(&ds);
        } else if (linkAction & TCL_CREATE_HARD_LINK) {
            if (link(target, src) != 0) {
                return NULL;
            }
        } else {
            errno = ENODEV;
            return NULL;
        }
        return toPtr;
    } else {
        Tcl_Obj *linkPtr = NULL;

        char link[MAXPATHLEN];
        int length;
        Tcl_DString ds;
        Tcl_Obj *transPtr;

        transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
        if (transPtr == NULL) {
            return NULL;
        }
        Tcl_DecrRefCount(transPtr);

        length = readlink(Tcl_FSGetNativePath(pathPtr), link, sizeof(link));
        if (length < 0) {
            return NULL;
        }

        Tcl_ExternalToUtfDString(NULL, link, length, &ds);
        linkPtr = TclDStringToObj(&ds);
        Tcl_IncrRefCount(linkPtr);
        return linkPtr;
    }
}
Beispiel #9
0
int job_save(

  job *pjob,  /* pointer to job structure */
  int  updatetype) /* 0=quick, 1=full     */

  {
  int fds;
  int i;
  char namebuf1[MAXPATHLEN];
  char namebuf2[MAXPATHLEN];
  int openflags;
  int redo;

  strcpy(namebuf1, path_jobs); /* job directory path */
  strcat(namebuf1, pjob->ji_qs.ji_fileprefix);
  strcpy(namebuf2, namebuf1); /* setup for later */

#ifdef PBS_MOM
  strcat(namebuf1, JOB_FILE_SUFFIX);
#else

  if (pjob->ji_is_array_template == TRUE)
    {
    strcat(namebuf1, JOB_FILE_TMP_SUFFIX);
    }
  else
    {
    strcat(namebuf1, JOB_FILE_SUFFIX);
    }

#endif

  /* if ji_modified is set, ie an attribute changed, then update mtime */

  if (pjob->ji_modified)
    {
    pjob->ji_wattr[JOB_ATR_mtime].at_val.at_long = time_now;
    }

  if (updatetype == SAVEJOB_QUICK)
    {
    openflags = O_WRONLY | O_Sync;

    /* NOTE:  open, do not create */

    fds = open(namebuf1, openflags, 0600);

    if (fds < 0)
      {
      char tmpLine[1024];

      snprintf(tmpLine, sizeof(tmpLine), "cannot open file '%s' for job %s in state %s (%s)",
               namebuf1,
               pjob->ji_qs.ji_jobid,
               PJobSubState[MAX(0,pjob->ji_qs.ji_substate)],
               (updatetype == 0) ? "quick" : "full");

      log_err(errno, "job_save", tmpLine);

      /* FAILURE */

      return(-1);
      }

    /* just write the "critical" base structure to the file */

    while ((i = write(fds, (char *) & pjob->ji_qs, quicksize)) != (ssize_t)quicksize)
      {
      if ((i < 0) && (errno == EINTR))
        {
        /* retry the write */

        if (lseek(fds, (off_t)0, SEEK_SET) < 0)
          {
          log_err(errno, "job_save", "lseek");

          close(fds);

          return(-1);
          }

        continue;
        }
      else
        {
        log_err(errno, "job_save", "quickwrite");

        close(fds);

        /* FAILURE */

        return(-1);
        }
      }

    close(fds);
    }
  else /* SAVEJOB_FULL, SAVEJOB_NEW, SAVEJOB_ARY */
    {
    /*
     * write the whole structure to the file.
     * For a update, this is done to a new file to protect the
     * old against crashs.
     * The file is written in four parts:
     * (1) the job structure,
     * (2) the attribtes in "encoded" form,
     * (3) the attributes in the "external" form, and last
     * (4) the dependency list.
     */

    strcat(namebuf2, JOB_FILE_COPY);

    openflags = O_CREAT | O_WRONLY | O_Sync;

    /* NOTE:  create file if required */

    if (updatetype == SAVEJOB_NEW)
      fds = open(namebuf1, openflags, 0600);
    else
      fds = open(namebuf2, openflags, 0600);

    if (fds < 0)
      {
      log_err(errno, "job_save", "open for full save");

      return(-1);
      }

    for (i = 0;i < MAX_SAVE_TRIES;++i)
      {
      redo = 0; /* try to save twice */

      save_setup(fds);

      if (save_struct((char *)&pjob->ji_qs, (size_t)quicksize) != 0)
        {
        redo++;
        }
      else if (save_attr(job_attr_def, pjob->ji_wattr, (int)JOB_ATR_LAST) != 0)
        {
        redo++;
        }

#ifdef PBS_MOM
      else if (save_tmsock(pjob) != 0)
        {
        redo++;
        }

#endif  /* PBS_MOM */
      else if (save_flush() != 0)
        {
        redo++;
        }

      if (redo != 0)
        {
        if (lseek(fds, (off_t)0, SEEK_SET) < 0)
          {
          log_err(errno, "job_save", "full lseek");
          }
        }
      else
        {
        break;
        }
      }  /* END for (i) */

    close(fds);

    if (i >= MAX_SAVE_TRIES)
      {
      if (updatetype == SAVEJOB_FULL)
        unlink(namebuf2);

      return(-1);
      }

    if (updatetype == SAVEJOB_FULL)
      {
      unlink(namebuf1);

      if (link(namebuf2, namebuf1) == -1)
        {
        LOG_EVENT(
          PBSEVENT_ERROR | PBSEVENT_SECURITY,
          PBS_EVENTCLASS_JOB,
          pjob->ji_qs.ji_jobid,
          "Link in job_save failed");
        }
      else
        {
        unlink(namebuf2);
        }
      }

    pjob->ji_modified = 0;
    }  /* END (updatetype == SAVEJOB_QUICK) */

  return(0);
  }  /* END job_save() */
Beispiel #10
0
int main(
    int              argc,
    char            *argv[])
{

    glob_t                   gbuf;
    int                      grc, i;
    GString                 *cmd;
    GError                  *err = NULL;

    GMainLoop *loop;

    GPtrArray    *child_args     = NULL;

    /* parse options */
    parse_options(&argc, &argv);

    /* set up logging */
    if (!logc_setup(&err)) {
        air_opterr("%s", err->message);
    }

    if (fd_nextdir == NULL) {
        air_opterr("The --nextdir switch is required");
    }

    child_args = g_ptr_array_sized_new(64);
    for (i=1; i < argc; i++) {
        /* Double dash indicates end of filedaemon's arguments */
        if (!strncmp(argv[i], "--", strlen(argv[i])) )
            continue;
        g_ptr_array_add(child_args, g_strdup(argv[i]));
    }
    g_ptr_array_add(child_args, NULL);

    if (child_args->len > 1) {
        if (fd_faildir == NULL) {
            air_opterr("The --faildir switch is required");
        }
    }

    cmd  = g_string_new("");

    loop = g_main_loop_new(NULL, FALSE);

    /* We need an input glob */
    if (!fd_inspec) {
        air_opterr("Input glob must be specified");
    }

    /* If an output destination is provided, make sure it's a directory */
    if (fd_outspec && !g_file_test(fd_outspec, G_FILE_TEST_IS_DIR )) {
        air_opterr("Output is not a directory");
    }

    /* Options check out; daemonize */
    if (!fd_nodaemon) {
        if (!daemonize()) {
            goto end;
        }
    }

    while (1) {
        /* Evaluate glob expression */
        grc = glob(fd_inspec, 0, NULL, &gbuf);

        if (grc == GLOB_NOSPACE) {
            g_error("Out of memory: glob allocation failure");
        }
#ifdef GLOB_NOMATCH
        /* HaX0riffic! Simulate behavior without NOMATCH where we have it. */
        else if (grc == GLOB_NOMATCH) {
            gbuf.gl_pathc = 0;
            gbuf.gl_pathv = NULL;
        }
#endif

        /* Iterate over glob paths, enqueueing. */
        for (i = 0; i < gbuf.gl_pathc; i++) {
            char      **child_envp            = {NULL};
            GError     *child_err             = NULL;

            GString    *filename_in           = NULL;
            GString    *filename_out          = NULL;
            GString    *filename_lock         = NULL;

            GIOChannel *file_in               = NULL;
            GIOChannel *file_out              = NULL;

            GIOChannel *child_stdin           = NULL;
            gint        child_stdin_fd        = -1;

            GIOChannel *child_stdout          = NULL;
            gint        child_stdout_fd       = -1;

            GPid          child_pid;
            int         len;

            fd_read_data_t  read_data;
            fd_write_data_t write_data;

            filename_in = g_string_new(gbuf.gl_pathv[i]);

            /* Skip non-regular files */
            if (!g_file_test(filename_in->str, G_FILE_TEST_IS_REGULAR) ) {
                g_string_free(filename_in, TRUE);
                continue;
            }

            /* Skip lockfiles */
            if (!strcmp(".lock", filename_in->str
                        + strlen(filename_in->str) - 5))
            {
                g_string_free(filename_in, TRUE);
                continue;
            }

            /* Generate lock path */
            if (!filename_lock) filename_lock = g_string_new("");
            g_string_printf(filename_lock, "%s.lock", filename_in->str);

            /* Skip files locked at queue time */
            if (g_file_test(filename_lock->str, G_FILE_TEST_IS_REGULAR)) {
                g_debug("file %s is locked", filename_in->str);
                g_string_free(filename_in, TRUE);
                g_string_free(filename_lock, TRUE);
                continue;
            }

            if (child_args->len == 1) {
                /* Do move or delete */
                GString *destpath = g_string_new("");
                char    *dbase    = NULL;
                /* Calculate move destination path */
                dbase = g_path_get_basename(filename_in->str);

                g_string_printf(destpath, "%s/%s", fd_nextdir, dbase);
                if (dbase) free(dbase);
                /* Do link */
                g_message("moving %s -> %s", filename_in->str, fd_nextdir);
                if (link(filename_in->str, destpath->str) < 0)
                    g_critical(
                        "error moving input file to destination directory: %s",
                        strerror(errno));
                /* Do delete */
                if (unlink(filename_in->str) < 0) {
                    g_critical("error deleting input file");
                }
                g_string_free(destpath, TRUE);
                g_string_free(filename_in, TRUE);
                g_string_free(filename_lock, TRUE);
                continue;
            }

            if (fd_lock) {
                fd_lock_file(filename_in->str);
            }

            file_in = g_io_channel_new_file(filename_in->str, "r", &err);

            if (file_in == NULL) {
                g_critical("Cannot open input file!");
            }

            g_io_channel_set_encoding(file_in, NULL, &err);

            if (err) {
                g_critical("error setting input encoding!");
            }

            g_io_channel_set_buffer_size(file_in, fd_bufsize);

            filename_out = g_string_new("");

            if (fd_outspec == NULL) {
                g_string_printf(filename_out, "%s", gbuf.gl_pathv[i]);
            } else {
                g_string_printf(filename_out, "%s/%s", fd_outspec,
                                gbuf.gl_pathv[i]);
            }

            len  = filename_out->len;

            if (g_strrstr(filename_out->str, ".")) {
                while (len-- > 0
                       && !g_str_has_suffix(filename_out->str, ".") )
                {
                    g_string_set_size(filename_out, filename_out->len - 1);
                }
                g_string_set_size(filename_out, filename_out->len - 1);
            }
            if (fd_outext) {
                g_string_append_printf(filename_out, ".%s", fd_outext);
            } else {
                g_string_append(filename_out, ".out");
            }

            g_message("%d: %s -> %s", i, filename_in->str, filename_out->str);

            file_out = g_io_channel_new_file(filename_out->str, "w", &err);

            if (file_out == NULL) {
                g_error("Cannot open output file!");
            }

            g_io_channel_set_encoding(file_out, NULL, &err);

            if (err) {
                g_error("error setting output encoding!");
            }

            g_io_channel_set_buffer_size(file_out, fd_bufsize);

            if (!g_spawn_async_with_pipes(".",
                                          (gchar **) child_args->pdata,
                                          child_envp,
                                          G_SPAWN_SEARCH_PATH |
                                          G_SPAWN_DO_NOT_REAP_CHILD,
                                          NULL,
                                          NULL,
                                          &child_pid,
                                          &child_stdin_fd,
                                          &child_stdout_fd,
                                          NULL,
                                          &child_err))
            {
                g_error("error spawning process: %s",
                        (child_err && child_err->message ? child_err->
                         message : "unknown error"));
            }
            g_debug("spawned process %d", i);

            /* Watch for process exit status */
            g_child_watch_add(child_pid, on_child_exit, filename_in->str);

            child_stdin = g_io_channel_unix_new(child_stdin_fd);

            if (child_stdin == NULL) {
                g_error("Cannot open child stdin!");
            }

            g_io_channel_set_encoding(child_stdin, NULL, &err);

            if (err) {
                g_error("error setting child stdin encoding!");
            }

            g_io_channel_set_buffer_size(child_stdin, fd_bufsize);

            child_stdout = g_io_channel_unix_new(child_stdout_fd);

            if (child_stdout == NULL) {
                g_error("Cannot open child stdout!");
            }

            g_io_channel_set_encoding(child_stdout, NULL, &err);

            if (err) {
                g_error("error setting child stdout encoding!");
            }


            g_io_channel_set_buffer_size(child_stdout, fd_bufsize);


            write_data.infile = file_in;
            write_data.buf    = g_malloc(g_io_channel_get_buffer_size(file_in));

            if (write_data.buf == NULL) {
                g_error("error allocating file_in buffer");
            }

            if (!g_io_add_watch(child_stdin,  G_IO_OUT | G_IO_PRI | G_IO_HUP |
                                G_IO_ERR, write_to_child, &write_data))
                g_error("Cannot add watch on GIOChannel!");

            read_data.outfile = file_out;
            read_data.loop    = loop;
            read_data.buf     = g_malloc(g_io_channel_get_buffer_size(file_out));

            if (write_data.buf == NULL) {
                g_error("error allocating file_in buffer");
            }

            if (!g_io_add_watch(child_stdout, G_IO_IN | G_IO_PRI | G_IO_HUP |
                                G_IO_ERR, read_from_child, &read_data))
                g_error("Cannot add watch on GIOChannel!");

            g_main_loop_run(loop);

            if (fd_lock) {
                fd_unlock_file(filename_in->str);
            }

            if (read_data.buf) {
                g_free(read_data.buf);
            }
            if (write_data.buf) {
                g_free(write_data.buf);
            }

            g_string_free(filename_in, TRUE);
            g_string_free(filename_out, TRUE);
            g_string_free(filename_lock, TRUE);
        }
        sleep(fd_poll_delay);
    }

  end:

    return 0;
}
Beispiel #11
0
int main (int argc,char *argv[])
{
  int ld,i;
  int tries = LOCKTIMEOUT * 60 - 1;
  char *s,*dir,*file,*lock,*hitch,tmp[1024];
  size_t dlen,len;
  struct stat sb,fsb;
  struct group *grp = getgrnam ("mail");
				/* get syslog */
  openlog (argv[0],LOG_PID,LOG_MAIL);
  if (!grp || (grp->gr_gid != getegid ()))
    return die ("not setgid mail",EX_USAGE);
  if (argc != 3) return die ("invalid arguments",EX_USAGE);
  for (s = argv[1]; *s; s++)
    if (!isdigit (*s)) return die ("invalid fd",EX_USAGE);
				/* find directory */
  if ((*argv[2] != '/') || !(file = strrchr (argv[2],'/')) || !file[1])
    return die ("invalid path",EX_USAGE);
				/* calculate lengths of directory and file */
  if (!(dlen = file - argv[2])) dlen = 1;
  len = strlen (++file);
				/* make buffers */
  dir = (char *) malloc (dlen + 1);
  lock = (char *) malloc (len + 6);
  hitch = (char *) malloc (len + 6 + 40 + MAXHOSTNAMELEN);
  if (!dir || !lock || !hitch) return die ("malloc failure",errno);
  strncpy (dir,argv[2],dlen);	/* connect to desired directory */
  dir[dlen] = '\0';
  printf ("dir=%s, file=%s\n",dir,file);
  chdir (dir);
				/* get device/inode of file descriptor */
  if (fstat (atoi (argv[1]),&fsb)) return die ("fstat failure",errno);
				/* better be a regular file */
  if ((fsb.st_mode & S_IFMT) != S_IFREG)
    return die ("fd not regular file",EX_USAGE);
				/* now get device/inode of file */
  if (lstat (file,&sb)) return die ("lstat failure",errno);
				/* does it match? */
  if ((sb.st_mode & S_IFMT) != S_IFREG)
    return die ("name not regular file",EX_USAGE);
  if ((sb.st_dev != fsb.st_dev) || (sb.st_ino != fsb.st_ino))
    return die ("fd and name different",EX_USAGE);
				/* build lock filename */
  sprintf (lock,"%s.lock",file);
  if (!lstat (lock,&sb) && ((sb.st_mode & S_IFMT) != S_IFREG))
    return die ("existing lock not regular file",EX_NOPERM);

  do {				/* until OK or out of tries */
    if (!stat (lock,&sb) && (time (0) > (sb.st_ctime + LOCKTIMEOUT * 60)))
      unlink (lock);		/* time out lock if enough time has passed */
    /* SUN-OS had an NFS
     * As kludgy as an albatross;
     * And everywhere that it was installed,
     * It was a total loss.
     * -- MRC 9/25/91
     */
				/* build hitching post file name */
    sprintf (hitch,"%s.%lu.%lu.",lock,(unsigned long) time (0),
	     (unsigned long) getpid ());
    len = strlen (hitch);	/* append local host name */
    gethostname (hitch + len,MAXHOSTNAMELEN);
				/* try to get hitching-post file */
    if ((ld = open (hitch,O_WRONLY|O_CREAT|O_EXCL,LOCKPROTECTION)) >= 0) {
				/* make sure others can break the lock */
      chmod (hitch,LOCKPROTECTION);
				/* get device/inode of hitch file */
      if (fstat (ld,&fsb)) return die ("hitch fstat failure",errno);
      close (ld);		/* close the hitching-post */
      /* Note: link() may return an error even if it actually succeeded.  So we
       * always check for success via the link count, and ignore the error if
       * the link count is right.
       */
				/* tie hitching-post to lock */
      i = link (hitch,lock) ? errno : 0;
				/* success if link count now 2 */
      if (stat (hitch,&sb) || (sb.st_nlink != 2) ||
	  (fsb.st_dev != sb.st_dev) || (fsb.st_ino != sb.st_ino)) {
	ld = -1;		/* failed to hitch */
	if (i == EPERM) {	/* was it because links not allowed? */
	  /* Probably a FAT filesystem on Linux.  It can't be NFS, so try
	   * creating the lock file directly.
	   */
	  if ((ld = open (lock,O_WRONLY|O_CREAT|O_EXCL,LOCKPROTECTION)) >= 0) {
	    /* get device/inode of lock file */
	    if (fstat (ld,&fsb)) return die ("lock fstat failure",errno);
	    close (ld);		/* close the file */
	  }
				/* give up immediately if protection failure */
	  else if (errno != EEXIST) tries = 0;
	}
      }
      unlink (hitch);		/* flush hitching post */
    }
				/* give up immediately if protection failure */
    else if (errno == EACCES) tries = 0;
    if (ld < 0) {		/* lock failed */
      if (tries--) sleep (1);	/* sleep 1 second and try again */
      else {
	write (1,"-",1);	/* hard failure */
	return EX_CANTCREAT;
      }
    }
  } while (ld < 0);
  write (1,"+",1);		/* indicate that all is well */
  read (0,tmp,1);		/* read continue signal from parent */
				/* flush the lock file */
  if (!stat (lock,&sb) && (fsb.st_dev == sb.st_dev) &&
      (fsb.st_ino == sb.st_ino)) unlink (lock);
  else syslog (LOG_NOTICE,"lock file %s/%s changed dev/inode",dir,lock);
  return EX_OK;
}
Beispiel #12
0
/* dump_all_front_end_state - save the state of all front_end nodes to file */
extern int dump_all_front_end_state(void)
{
#ifdef HAVE_FRONT_END
    /* Save high-water mark to avoid buffer growth with copies */
    static int high_buffer_size = (1024 * 1024);
    int error_code = 0, i, log_fd;
    char *old_file, *new_file, *reg_file;
    front_end_record_t *front_end_ptr;
    /* Locks: Read config and node */
    slurmctld_lock_t node_read_lock = { READ_LOCK, NO_LOCK, READ_LOCK,
                                        NO_LOCK
                                      };
    Buf buffer = init_buf(high_buffer_size);
    DEF_TIMERS;

    START_TIMER;
    /* write header: version, time */
    packstr(FRONT_END_STATE_VERSION, buffer);
    pack_time(time(NULL), buffer);

    /* write node records to buffer */
    lock_slurmctld (node_read_lock);

    for (i = 0, front_end_ptr = front_end_nodes;
            i < front_end_node_cnt; i++, front_end_ptr++) {
        xassert(front_end_ptr->magic == FRONT_END_MAGIC);
        _dump_front_end_state(front_end_ptr, buffer);
    }

    old_file = xstrdup (slurmctld_conf.state_save_location);
    xstrcat (old_file, "/front_end_state.old");
    reg_file = xstrdup (slurmctld_conf.state_save_location);
    xstrcat (reg_file, "/front_end_state");
    new_file = xstrdup (slurmctld_conf.state_save_location);
    xstrcat (new_file, "/front_end_state.new");
    unlock_slurmctld (node_read_lock);

    /* write the buffer to file */
    lock_state_files();
    log_fd = creat (new_file, 0600);
    if (log_fd < 0) {
        error ("Can't save state, error creating file %s %m", new_file);
        error_code = errno;
    } else {
        int pos = 0, nwrite = get_buf_offset(buffer), amount, rc;
        char *data = (char *)get_buf_data(buffer);
        high_buffer_size = MAX(nwrite, high_buffer_size);
        while (nwrite > 0) {
            amount = write(log_fd, &data[pos], nwrite);
            if ((amount < 0) && (errno != EINTR)) {
                error("Error writing file %s, %m", new_file);
                error_code = errno;
                break;
            }
            nwrite -= amount;
            pos    += amount;
        }

        rc = fsync_and_close(log_fd, "front_end");
        if (rc && !error_code)
            error_code = rc;
    }
    if (error_code)
        (void) unlink (new_file);
    else {	/* file shuffle */
        (void) unlink (old_file);
        if (link(reg_file, old_file))
            debug4("unable to create link for %s -> %s: %m",
                   reg_file, old_file);
        (void) unlink (reg_file);
        if (link(new_file, reg_file))
            debug4("unable to create link for %s -> %s: %m",
                   new_file, reg_file);
        (void) unlink (new_file);
    }
    xfree (old_file);
    xfree (reg_file);
    xfree (new_file);
    unlock_state_files ();

    free_buf (buffer);
    END_TIMER2("dump_all_front_end_state");
    return error_code;
#else
    return SLURM_SUCCESS;
#endif
}
Beispiel #13
0
int
run_attr_tests(char *testfile)
{
    int ret = -1;
    char *res = NULL;
    struct stat buf;
    struct statfs sbuf;
    struct statvfs svbuf;

    assert(testfile);

    fprintf(stdout, "Testing chmod");
    ret = chmod(testfile, 0);
    check_err(ret, "chmod", 2);

    fprintf(stdout, "Testing chown");
    ret = chown(testfile, 0, 0);
    check_err(ret, "chown", 2);

    fprintf(stdout, "Testing link");
    ret = link(testfile, testfile);
    check_err(ret, "link", 2);

    fprintf(stdout, "Testing rename");
    ret = rename(testfile, testfile);
    check_err(ret, "rename", 2);

    fprintf(stdout, "Testing utimes");
    ret = utimes(testfile, NULL);
    check_err(ret, "utimes", 2);

    fprintf(stdout, "Testing utime");
    ret = utime(testfile, NULL);
    check_err(ret, "utime", 2);

    fprintf(stdout, "Testing unlink");
    ret = unlink(testfile);
    check_err(ret, "unlink", 2);

    fprintf(stdout, "Testing symlink");
    ret = symlink(testfile, testfile);
    check_err(ret, "symlink", 2);

    fprintf(stdout, "Testing readlink");
    ret = readlink(testfile, testfile, 0);
    check_err(ret, "readlink", 2);

    fprintf(stdout, "Testing realpath");
    ret = 0;
    res = realpath((const char *)testfile, testfile);
    if (!res)
        ret = -1;
    check_err(ret, "realpath", 2);

    fprintf(stdout, "Testing stat");
    ret = stat(testfile, &buf);
    check_err(ret, "stat", 1);

    fprintf(stdout, "Testing lstat");
    ret = lstat(testfile, &buf);
    check_err(ret, "lstat", 1);

    fprintf(stdout, "Testing statfs");
    ret = statfs(testfile, &sbuf);
    check_err(ret, "statfs", 2);

    fprintf(stdout, "Testing statvfs");
    ret = statvfs(testfile, &svbuf);
    check_err(ret, "statvfs", 1);

    fprintf(stdout, "Testing getxattr");
    ret = getxattr(testfile, NULL, NULL, 0);
    check_err(ret, "getxattr", 2);

    fprintf(stdout, "Testing lgetxattr");
    ret = lgetxattr(testfile, NULL, NULL, 0);
    check_err(ret, "lgetxattr", 1);

    fprintf(stdout, "Testing lchown");
    ret = lchown(testfile, 0, 0);
    check_err(ret, "lchown", 2);
    return 0;
}
Beispiel #14
0
static int
do_lock_file(const char *file, const char *lock)
{
	int fd;
	int pid;
	int len;
	int retval;
	char buf[32];

	if ((fd = open(file, O_CREAT|O_EXCL|O_WRONLY, 0600)) == -1)
		return 0;

	pid = getpid();
	snprintf(buf, sizeof buf, "%d", pid);
	len = strlen(buf) + 1;
	if (write(fd, buf, len) != len) {
		close(fd);
		unlink(file);
		return 0;
	}
	close(fd);

	if (link(file, lock) == 0) {
		retval = check_link_count(file);
		unlink(file);
		return retval;
	}

	if ((fd = open(lock, O_RDWR)) == -1) {
		unlink(file);
		errno = EINVAL;
		return 0;
	}
	len = read(fd, buf, sizeof(buf) - 1);
	close(fd);
	if (len <= 0) {
		unlink(file);
		errno = EINVAL;
		return 0;
	}
	buf[len] = '\0';
	if ((pid = strtol(buf, (char **) 0, 10)) == 0) {
		unlink(file);
		errno = EINVAL;
		return 0;
	}
	if (kill(pid, 0) == 0)  {
		unlink(file);
		errno = EEXIST;
		return 0;
	}
	if (unlink(lock) != 0) {
		unlink(file);
		return 0;
	}

	retval = 0;
	if (link(file, lock) == 0 && check_link_count(file))
		retval = 1;

	unlink(file);
	return retval;
}
Beispiel #15
0
void CPU::branch(uint32_t address, bool lk) {
	if (lk)
		link();

	pc = address;
}
Beispiel #16
0
/*
 * Like fgets, but go through the list of files chaining them together.
 * Set len to the length of the line.
 */
int
mf_fgets(SPACE *sp, enum e_spflag spflag)
{
	struct stat sb, nsb;
	ssize_t len;
	static char *p = NULL;
	static size_t plen = 0;
	int c;
	static int firstfile;

	if (infile == NULL) {
		/* stdin? */
		if (files->fname == NULL) {
			if (inplace != NULL)
				errx(1,
				    _("-I or -i may not be used with stdin"));
			infile = stdin;
			fname = "stdin";
			outfile = stdout;
			outfname = "stdout";
		}
		firstfile = 1;
	}

	for (;;) {
		if (infile != NULL && (c = getc(infile)) != EOF) {
			(void) ungetc(c, infile);
			break;
		}
		/* If we are here then either eof or no files are open yet */
		if (infile == stdin) {
			sp->len = 0;
			return (0);
		}
		if (infile != NULL) {
			(void) fclose(infile);
			if (*oldfname != '\0') {
				/* if there was a backup file, remove it */
				(void) unlink(oldfname);
				/*
				 * Backup the original.  Note that hard links
				 * are not supported on all filesystems.
				 */
				if ((link(fname, oldfname) != 0) &&
				    (rename(fname, oldfname) != 0)) {
					warn("rename()");
					if (*tmpfname)
						(void) unlink(tmpfname);
					exit(1);
				}
				*oldfname = '\0';
			}
			if (*tmpfname != '\0') {
				if (outfile != NULL && outfile != stdout)
					if (fclose(outfile) != 0) {
						warn("fclose()");
						(void) unlink(tmpfname);
						exit(1);
					}
				outfile = NULL;
				if (rename(tmpfname, fname) != 0) {
					/* this should not happen really! */
					warn("rename()");
					(void) unlink(tmpfname);
					exit(1);
				}
				*tmpfname = '\0';
			}
			outfname = NULL;
		}
		if (firstfile == 0)
			files = files->next;
		else
			firstfile = 0;
		if (files == NULL) {
			sp->len = 0;
			return (0);
		}
		fname = files->fname;
		if (inplace != NULL) {
			char bn[PATH_MAX];
			char dn[PATH_MAX];
			(void) strlcpy(bn, fname, sizeof (bn));
			(void) strlcpy(dn, fname, sizeof (dn));
			if (lstat(fname, &sb) != 0)
				err(1, "%s", fname);
			if (!(sb.st_mode & S_IFREG))
				fatal(_("in-place editing only "
				    "works for regular files"));
			if (*inplace != '\0') {
				(void) strlcpy(oldfname, fname,
				    sizeof (oldfname));
				len = strlcat(oldfname, inplace,
				    sizeof (oldfname));
				if (len > sizeof (oldfname))
					fatal(_("name too long"));
			}
			len = snprintf(tmpfname, sizeof (tmpfname),
			    "%s/.!%ld!%s", dirname(dn), (long)getpid(),
			    basename(bn));
			if (len >= sizeof (tmpfname))
				fatal(_("name too long"));
			(void) unlink(tmpfname);
			if ((outfile = fopen(tmpfname, "w")) == NULL)
				err(1, "%s", fname);
			/*
			 * Some file systems don't support chown or
			 * chmod fully.  On those, the owner/group and
			 * permissions will already be set to what
			 * they need to be.
			 */
			if (fstat(fileno(outfile), &nsb) != 0) {
				warn("fstat()");
			}
			if (((sb.st_uid != nsb.st_uid) ||
			    (sb.st_gid != nsb.st_gid)) &&
			    (fchown(fileno(outfile), sb.st_uid, sb.st_gid)
			    != 0))
				warn("fchown()");
			if ((sb.st_mode != nsb.st_mode) &&
			    (fchmod(fileno(outfile), sb.st_mode & 07777) != 0))
				warn("fchmod()");
			outfname = tmpfname;
			if (!ispan) {
				linenum = 0;
				resetstate();
			}
		} else {
			outfile = stdout;
			outfname = "stdout";
		}
		if ((infile = fopen(fname, "r")) == NULL) {
			warn("%s", fname);
			rval = 1;
			continue;
		}
	}
	/*
	 * We are here only when infile is open and we still have something
	 * to read from it.
	 *
	 * Use getline() so that we can handle essentially infinite
	 * input data.  The p and plen are static so each invocation gives
	 * getline() the same buffer which is expanded as needed.
	 */
	len = getline(&p, &plen, infile);
	if (len == -1)
		err(1, "%s", fname);
	if (len != 0 && p[len - 1] == '\n')
		len--;
	cspace(sp, p, len, spflag);

	linenum++;

	return (1);
}
Beispiel #17
0
void CPU::exec32(const Instruction32 &insn) {
	switch(insn.OP) {
		case 0x00: {
				uint32_t &rD = r[insn.spform.rD];
				uint32_t &rA = r[insn.spform.rA];
				uint32_t &rB = r[insn.spform.rB];
				switch(insn.spform.func6) {
					// nop
					case 0x00: /* nothing */ break;

					// br{cond}[l] rA
					case 0x04: if(conditional(insn.spform.rB)) branch(rA - 4, insn.spform.CU); break;

					// add[.c] rD, rA, rB
					case 0x08: rD = add(rA, rB, insn.spform.CU); break;
					// addc[.c] rD, rA, rB
					case 0x09: rD = addc(rA, rB, insn.spform.CU); break;
					// sub[.c] rD, rA, rB
					case 0x0A: rD = sub(rA, rB, insn.spform.CU); break;
					// subc[.c] rD, rA, rB
					case 0x0B: rD = subc(rA, rB, insn.spform.CU); break;
					// cmp{tcs}.c rA, rB
					case 0x0C:      cmp(rA, rB, insn.spform.rD & 0x03, insn.spform.CU); break;
					// cmpz{tcs}.c rA, rB
					case 0x0D:      cmp(rA, 0, insn.spform.rD & 0x03, insn.spform.CU); break;

					// neg[.c] rD, rA
					case 0x0F: rD = sub(0, rA, insn.spform.CU); break;
					// and[.c] rD, rA, rB
					case 0x10: rD = bit_and(rA, rB, insn.spform.CU); break;
					// or[.c] rD, rA, rB
					case 0x11: rD = bit_or(rA, rB, insn.spform.CU); break;
					// not[.c] rD, rA, rB
					case 0x12: rD = bit_xor(rA, ~0, insn.spform.CU); break;
					// xor[.c] rD, rA, rB
					case 0x13: rD = bit_or(rA, rB, insn.spform.CU); break;
					// bitclr[.c] rD, rA, imm5
					case 0x14: rD = bit_and(rA, ~(1 << insn.spform.rB), insn.spform.CU); break;
					// bitset[.c] rD, rA, imm5
					case 0x15: rD = bit_or(rA, 1 << insn.spform.rB, insn.spform.CU); break;
					// bittst.c rA, imm5
					case 0x16: bit_and(rA, 1 << insn.spform.rB, insn.spform.CU); break;
					// bittgl[.c] rA, imm5
					case 0x17: rD = bit_xor(rA, 1 << insn.spform.rB, insn.spform.CU); break;
					// sll[.c] rA, imm5
					case 0x18: rD = sll(rA, insn.spform.rB, insn.spform.CU); break;
					// srl[.c] rA, imm5
					case 0x1A: rD = srl(rA, insn.spform.rB, insn.spform.CU); break;
					// sra[.c] rA, imm5
					case 0x1B: rD = sra(rA, insn.spform.rB, insn.spform.CU); break;

					// mul rA, rD
					case 0x20: ce_op(rA, rD, std::multiplies<int64_t>()); break;
					// mulu rA, rD
					case 0x21: ce_op(rA, rD, std::multiplies<uint64_t>()); break;
					// div rA, rD
					case 0x22: ce_op(rA, rD, std::divides<int64_t>()); break;
					// divu rA, rD
					case 0x23: ce_op(rA, rD, std::divides<uint64_t>()); break;

					// mfce{hl} rD[, rA]
					case 0x24:
							switch(insn.spform.rB) {
								case 0x01: rD = CEL; break;
								case 0x02: rD = CEH; break;
								case 0x03: rD = CEH; rA = CEL; break;
							}
						break;
					// mtce{hl} rD[, rA]
					case 0x25:
							switch(insn.spform.rB) {
								case 0x01: CEL = rD; break;
								case 0x02: CEH = rD; break;
								case 0x03: CEH = rD; CEL = rA; break;
							}
						break;

					// mfsr rA, Srn
					case 0x28: rA = sr[insn.spform.rB];
					// mtsr rA, Srn
					case 0x29: sr[insn.spform.rB] = rA;
					// t{cond}
					case 0x2A: T = conditional(insn.spform.rB); break;
					// mv{cond} rD, rA
					case 0x2B: if(conditional(insn.spform.rB)) rD = rA; break;
					// extsb[.c] rD, rA
					case 0x2C: rD = sign_extend(rA,  8); if(insn.spform.CU) basic_flags(rD); break;
					// extsh[.c] rD, rA
					case 0x2D: rD = sign_extend(rA, 16); if(insn.spform.CU) basic_flags(rD); break;
					// extzb[.c] rD, rA
					case 0x2E: rD = bit_and(rA, 0x000000FF, insn.spform.CU); break;
					// extzh[.c] rD, rA
					case 0x2F: rD = bit_and(rA, 0x0000FFFF, insn.spform.CU); break;

					// slli[.c] rD, rA, imm5
					case 0x38: rD = sll(rA, insn.spform.rB, insn.spform.CU); break;

					// srli[.c] rD, rA, imm5
					case 0x3A: rD = srl(rA, insn.spform.rB, insn.spform.CU); break;
					// srai[.c] rD, rA, imm5
					case 0x3B: rD = sra(rA, insn.spform.rB, insn.spform.CU); break;

					default: debugDump();
				}
			} break;
		case 0x01: {
				uint32_t &rD = r[insn.iform.rD];
				switch(insn.iform.func3) {
					// addi[.c] rD, imm16
					case 0x00: rD = add(rD, sign_extend(insn.iform.Imm16, 16), insn.iform.CU); break;
					// cmpi.c rD, imm16
					case 0x02:      cmp(rD, sign_extend(insn.iform.Imm16, 16), 3, insn.iform.CU); break;
					// andi.c rD, imm16
					case 0x04: rD = bit_and(rD, insn.iform.Imm16, insn.iform.CU); break;
					// ori.c rD, imm16
					case 0x05: rD = bit_or(rD, insn.iform.Imm16, insn.iform.CU); break;
					// ldi rD, imm16
					case 0x06: rD = sign_extend(insn.iform.Imm16, 16); break;

					default: debugDump();
				}
			} break;
		case 0x02: {
				// j[l] imm24
				if(insn.jform.LK)
					link();

				// Update PC
				pc &= 0xFC000000;
				pc |= (insn.jform.Disp24 << 1) - 4;
			} break;
		case 0x03: {
				uint32_t &rD = r[insn.rixform.rD];
				uint32_t &rA = r[insn.rixform.rA];

				// Pre-increment
				rA += sign_extend(insn.rixform.Imm12, 12);
				switch(insn.rixform.func3) {
					// lw rD, [rA, imm12]+
					case 0x00: rD = miu.readU32(rA); break;
					// lh rD, [rA, imm12]+
					case 0x01: rD = sign_extend(miu.readU16(rA), 16); break;
					// lhu rD, [rA, imm12]+
					case 0x02: rD = miu.readU16(rA); break;
					// lb rD, [rA, imm12]+
					case 0x03: rD = sign_extend(miu.readU8(rA), 8); break;
					// sw rD, [rA, imm12]+
					case 0x04: miu.writeU32(rA, rD); break;
					// sh rD, [rA, imm12]+
					case 0x05: miu.writeU16(rA, rD); break;
					// lbu rD, [rA, imm12]+
					case 0x06: rD = miu.readU8(rA); break;
					// sb rD, [rA, imm12]+
					case 0x07: miu.writeU8(rA, rD); break;

					default: debugDump();
				}
			} break;
		case 0x04: {
				// b{cond}[l]
				if(conditional(insn.bcform.BC)) {
					if(insn.bcform.LK)
						link();

					pc += sign_extend(((insn.bcform.Disp18_9 << 9) | insn.bcform.Disp8_0) << 1, 20) - 4;
				}
			} break;
		case 0x05: {
				uint32_t &rD = r[insn.iform.rD];
				uint32_t imm16 = insn.iform.Imm16 << 16;
				switch(insn.iform.func3) {
					// addis[.c] rD, imm16
					case 0x00: rD = add(rD, imm16, insn.iform.CU); break;
					// cmpis.c rD, imm16
					case 0x02:      cmp(rD, imm16, 3, insn.iform.CU); break;
					// andis.c rD, imm16
					case 0x04: rD = bit_and(rD, imm16, insn.iform.CU); break;
					// oris.c rD, imm16
					case 0x05: rD = bit_or(rD, imm16, insn.iform.CU); break;
					// ldis rD, imm16
					case 0x06: rD = imm16; break;

					default: debugDump();
				}
			} break;
		case 0x06: {
				uint32_t &rD = r[insn.crform.rD];
				uint32_t &crA = cr[insn.crform.crA];
				switch(insn.crform.CR_OP) {
					// mtcr rD, crA
					case 0x00: crA = rD; break;
					// mfcr rD, crA
					case 0x01: rD = crA; break;
					// rte
					case 0x84: branch(cr5 - 4, false); /* TODO: missing PSR */ break;

					default: debugDump();
				}
			} break;
		case 0x07: {
				uint32_t &rD = r[insn.rixform.rD];
				uint32_t &rA = r[insn.rixform.rA];
				switch(insn.rixform.func3) {
					// lw rD, [rA]+, imm12
					case 0x00: rD = miu.readU32(rA); break;
					// lh rD, [rA]+, imm12
					case 0x01: rD = sign_extend(miu.readU16(rA), 16); break;
					// lhu rD, [rA]+, imm12
					case 0x02: rD = miu.readU16(rA); break;
					// lb rD, [rA]+, imm12
					case 0x03: rD = sign_extend(miu.readU8(rA), 8); break;
					// sw rD, [rA]+, imm12
					case 0x04: miu.writeU32(rA, rD); break;
					// sh rD, [rA]+, imm12
					case 0x05: miu.writeU16(rA, rD); break;
					// lbu rD, [rA]+, imm12
					case 0x06: rD = miu.readU8(rA); break;
					// sb rD, [rA]+, imm12
					case 0x07: miu.writeU8(rA, rD); break;

					default: debugDump();
				}
				// Post-increment
				rA += sign_extend(insn.rixform.Imm12, 12);
			} break;
		case 0x08: {
				// addri[.c] rD, rA, imm14
				uint32_t &rD = r[insn.riform.rD];
				uint32_t &rA = r[insn.riform.rA];
				uint32_t imm14 = sign_extend(insn.riform.Imm14, 14);

				rD = add(rA, imm14, insn.riform.CU);
			} break;
		case 0x0C: {
				// andri[.c] rD, rA, imm14
				uint32_t &rD = r[insn.riform.rD];
				uint32_t &rA = r[insn.riform.rA];
				uint32_t imm14 = insn.riform.Imm14;

				rD = bit_and(rA, imm14, insn.riform.CU);
			} break;
		case 0x0D: {
				// orri[.c] rD, rA, imm14
				uint32_t &rD = r[insn.riform.rD];
				uint32_t &rA = r[insn.riform.rA];
				uint32_t imm14 = insn.riform.Imm14;

				rD = bit_or(rA, imm14, insn.riform.CU);
			} break;
		case 0x10: {
				// lw rD, [rA, imm15]
				uint32_t &rD = r[insn.mform.rD];
				uint32_t &rA = r[insn.mform.rA];
				uint32_t imm15 = sign_extend(insn.mform.Imm15, 15);

				rD = miu.readU32(rA + imm15);
			} break;
		case 0x11: {
				// lh rD, [rA, imm15]
				uint32_t &rD = r[insn.mform.rD];
				uint32_t &rA = r[insn.mform.rA];
				uint32_t imm15 = sign_extend(insn.mform.Imm15, 15);

				rD = sign_extend(miu.readU16(rA + imm15), 16);
			} break;
		case 0x12: {
				// lhu rD, [rA, imm15]
				uint32_t &rD = r[insn.mform.rD];
				uint32_t &rA = r[insn.mform.rA];
				uint32_t imm15 = sign_extend(insn.mform.Imm15, 15);

				rD = miu.readU16(rA + imm15);
			} break;
		case 0x13: {
				// lb rD, [rA, imm15]
				uint32_t &rD = r[insn.mform.rD];
				uint32_t &rA = r[insn.mform.rA];
				uint32_t imm15 = sign_extend(insn.mform.Imm15, 15);

				rD = sign_extend(miu.readU8(rA + imm15), 8);
			} break;
		case 0x14: {
				// sw rD, [rA, imm15]
				uint32_t &rD = r[insn.mform.rD];
				uint32_t &rA = r[insn.mform.rA];
				uint32_t imm15 = sign_extend(insn.mform.Imm15, 15);

				miu.writeU32(rA + imm15, rD);
			} break;
		case 0x15: {
				// sh rD, [rA, imm15]
				uint32_t &rD = r[insn.mform.rD];
				uint32_t &rA = r[insn.mform.rA];
				uint32_t imm15 = sign_extend(insn.mform.Imm15, 15);

				miu.writeU16(rA + imm15, rD);
			} break;
		case 0x16: {
				// lbu rD, [rA, imm15]
				uint32_t &rD = r[insn.mform.rD];
				uint32_t &rA = r[insn.mform.rA];
				uint32_t imm15 = sign_extend(insn.mform.Imm15, 15);

				rD = miu.readU8(rA + imm15);
			} break;
		case 0x17: {
				// sb rD, [rA, imm15]
				uint32_t &rD = r[insn.mform.rD];
				uint32_t &rA = r[insn.mform.rA];
				uint32_t imm15 = sign_extend(insn.mform.Imm15, 15);

				miu.writeU8(rA + imm15, rD);
			} break;
		case 0x18:
				// cache op, [rA, imm15]
			break;
		default: debugDump();
	}
}
Beispiel #18
0
/* Save mbox changes. */
int
fetch_mbox_save(struct account *a, struct fetch_mbox_mbox *fmbox)
{
	struct fetch_mbox_data	*data = a->data;
	struct fetch_mbox_mail	*aux, *this;
	char			 path[MAXPATHLEN], saved[MAXPATHLEN], c;
	int			 fd;
	ssize_t			 n;
	struct iovec		 iov[2];

	log_debug2("%s: %s: saving mbox: %u kept, %u total",
	    a->name, fmbox->path, fmbox->reference, fmbox->total);
	fd = -1;

	/*
	 * If the reference count is 0, no mails were kept, so the mbox can
	 * just be truncated.
	 */
	if (fmbox->reference == 0) {
		if (fmbox->total != 0 && ftruncate(fmbox->fd, 0) != 0)
			goto error;
		goto free_all;
	}

	/* If all the mails were kept, do nothing. */
	if (fmbox->reference == fmbox->total)
		goto free_all;

	/*
	 * Otherwise, things get complicated. data->kept is a list of all the
	 * mails (struct fetch_mbox_mail) which were kept for ALL mailboxes.
	 * There is no guarantee it is ordered by offset. Rather than try to be
	 * clever and save disk space, just create a new mbox and copy all the
	 * kept mails into it.
	 */
	if (ppath(path, sizeof path, "%s.XXXXXXXXXX", fmbox->path) != 0)
		goto error;
	if (ppath(saved, sizeof saved, "%s.XXXXXXXXXX", fmbox->path) != 0)
		goto error;
	if ((fd = mkstemp(path)) == -1)
		goto error;

	aux = TAILQ_FIRST(&data->kept);
	while (aux != NULL) {
		this = aux;
		aux = TAILQ_NEXT(aux, entry);

		if (this->fmbox != fmbox)
			continue;

		log_debug2("%s: writing message from %zu, size %zu",
		    a->name, this->off, this->size);
		c = '\n';
		iov[0].iov_base = fmbox->base + this->off;
		iov[0].iov_len = this->size;
		iov[1].iov_base = &c;
		iov[1].iov_len = 1;
		if ((n = writev(fd, iov, 2)) < 0)
			goto error;
		if ((size_t) n != this->size + 1) {
			errno = EIO;
			goto error;
		}

		fetch_mbox_free(this);
		TAILQ_REMOVE(&data->kept, this, entry);
	}

	if (fsync(fd) != 0)
		goto error;
	close(fd);

	/*
	 * Do the replacement dance: create a backup copy of the mbox, remove
	 * the mbox, link in the temporary file, unlink the temporary file,
	 * then unlink the backup mbox. We don't try to recover if anything
	 * fails on the grounds that it could just make things worse, just
	 * die and let the user sort it out.
	 */
	if (link(fmbox->path, saved) != 0)
		goto error;
	if (unlink(fmbox->path) != 0)
		goto error;
	if (link(path, fmbox->path) != 0)
		goto error;
	if (unlink(path) != 0)
		goto error;
	if (unlink(saved) != 0)
		goto error;

free_all:
	aux = TAILQ_FIRST(&data->kept);
	while (aux != NULL) {
		this = aux;
		aux = TAILQ_NEXT(aux, entry);

		if (this->fmbox == fmbox)
			fetch_mbox_free(this);
	}

	if (fmbox->reference != 0)
		fatalx("dangling reference");

	return (0);

error:
	if (fd != -1) {
		close(fd);
		unlink(path);
	}
	log_warn("%s: %s", a->name, fmbox->path);
	return (-1);
}
/* If a pidfile has been configured, creates it and stores the running
 * process's pid in it.  Ensures that the pidfile will be deleted when the
 * process exits. */
static void
make_pidfile(void)
{
    long int pid = getpid();
    struct stat s;
    char *tmpfile;
    FILE *file;
    int error;

    /* Create a temporary pidfile. */
    tmpfile = xasprintf("%s.tmp%ld", pidfile, pid);
    fatal_signal_add_file_to_unlink(tmpfile);
    file = fopen(tmpfile, "w+");
    if (!file) {
        VLOG_FATAL("%s: create failed (%s)", tmpfile, strerror(errno));
    }

    if (fstat(fileno(file), &s) == -1) {
        VLOG_FATAL("%s: fstat failed (%s)", tmpfile, strerror(errno));
    }

    fprintf(file, "%ld\n", pid);
    if (fflush(file) == EOF) {
        VLOG_FATAL("%s: write failed (%s)", tmpfile, strerror(errno));
    }

    error = lock_pidfile(file, F_SETLK);
    if (error) {
        VLOG_FATAL("%s: fcntl(F_SETLK) failed (%s)", tmpfile, strerror(error));
    }

    /* Rename or link it to the correct name. */
    if (overwrite_pidfile) {
        if (rename(tmpfile, pidfile) < 0) {
            VLOG_FATAL("failed to rename \"%s\" to \"%s\" (%s)",
                       tmpfile, pidfile, strerror(errno));
        }
    } else {
        do {
            error = link(tmpfile, pidfile) == -1 ? errno : 0;
            if (error == EEXIST) {
                check_already_running();
            }
        } while (error == EINTR || error == EEXIST);
        if (error) {
            VLOG_FATAL("failed to link \"%s\" as \"%s\" (%s)",
                       tmpfile, pidfile, strerror(error));
        }
    }

    /* Ensure that the pidfile will get deleted on exit. */
    fatal_signal_add_file_to_unlink(pidfile);

    /* Delete the temporary pidfile if it still exists. */
    if (!overwrite_pidfile) {
        error = fatal_signal_unlink_file_now(tmpfile);
        if (error) {
            VLOG_FATAL("%s: unlink failed (%s)", tmpfile, strerror(error));
        }
    }

    /* Clean up.
     *
     * We don't close 'file' because its file descriptor must remain open to
     * hold the lock. */
    pidfile_dev = s.st_dev;
    pidfile_ino = s.st_ino;
    free(tmpfile);
    free(pidfile);
    pidfile = NULL;
}
Beispiel #20
0
int acquire_lock_file( const char *lockfile, const int timeout, int force )
{
	int fd, timed_out = 0;
	int ret = 0; /* early exit returns failure */
	struct timespec pollint;
	struct timeval start, end;
	double elapsed;
	struct stat statbuf;

	/*
	  (Re)create a unique file and check that it has one only link.
	*/
	char *linkfile = gen_unique_nfs_filename( lockfile );
	if( linkfile == NULL )
	{
		goto done;
	}
	(void)unlink( linkfile );
	if( ( fd = open( linkfile, O_CREAT|O_RDONLY, 0600 ) ) == -1 )
	{
		debug( 1, L"acquire_lock_file: open: %s", strerror( errno ) );
		goto done;
	}
	/*
	  Don't need to check exit status of close on read-only file descriptors
	*/
	close( fd );
	if( stat( linkfile, &statbuf ) != 0 )
	{
		debug( 1, L"acquire_lock_file: stat: %s", strerror( errno ) );
		goto done;
	}
	if ( statbuf.st_nlink != 1 )
	{
		debug( 1, L"acquire_lock_file: number of hardlinks on unique "
			   L"tmpfile is %d instead of 1.", (int)statbuf.st_nlink );
		goto done;
	}
	if( gettimeofday( &start, NULL ) != 0 )
	{
		debug( 1, L"acquire_lock_file: gettimeofday: %s", strerror( errno ) );
		goto done;
	}
	end = start;
	pollint.tv_sec = 0;
	pollint.tv_nsec = LOCKPOLLINTERVAL * 1000000;
	do
	{
		/*
		  Try to create a hard link to the unique file from the
		  lockfile.  This will only succeed if the lockfile does not
		  already exist.  It is guaranteed to provide race-free
		  semantics over NFS which the alternative of calling
		  open(O_EXCL|O_CREAT) on the lockfile is not.  The lock
		  succeeds if the call to link returns 0 or the link count on
		  the unique file increases to 2.
		*/
		if( link( linkfile, lockfile ) == 0 ||
		    ( stat( linkfile, &statbuf ) == 0 &&
			  statbuf.st_nlink == 2 ) )
		{
			/* Successful lock */
			ret = 1;
			break;
		}
		elapsed = end.tv_sec + end.tv_usec/1000000.0 -
			( start.tv_sec + start.tv_usec/1000000.0 );
		/*
		   The check for elapsed < 0 is to deal with the unlikely event
		   that after the loop is entered the system time is set forward
		   past the loop's end time.  This would otherwise result in a
		   (practically) infinite loop.
		*/
		if( timed_out || elapsed >= timeout || elapsed < 0 )
		{
			if ( timed_out == 0 && force )
			{
				/*
				  Timed out and force was specified - attempt to
				  remove stale lock and try a final time
				*/
				(void)unlink( lockfile );
				timed_out = 1;
				continue;
			}
			else
			{
				/*
				  Timed out and final try was unsuccessful or
				  force was not specified
				*/
				debug( 1, L"acquire_lock_file: timed out "
					   L"trying to obtain lockfile %s using "
					   L"linkfile %s", lockfile, linkfile );
				break;
			}
		}
		nanosleep( &pollint, NULL );
	} while( gettimeofday( &end, NULL ) == 0 );
  done:
	/* The linkfile is not needed once the lockfile has been created */
	(void)unlink( linkfile );
	free( linkfile );
	return ret;
}
Beispiel #21
0
static void _dump_sicp_state(void)
{
    char *old_file, *new_file, *reg_file;
    ListIterator sicp_iterator;
    sicp_job_t *sicp_ptr;
    Buf buffer;
    time_t now = time(NULL);
    int error_code = SLURM_SUCCESS, len, log_fd;

    pthread_mutex_lock(&sicp_lock);
    len = list_count(sicp_job_list) * 4 + 128;
    buffer = init_buf(len);

    packstr("PROTOCOL_VERSION", buffer);
    pack16(SLURM_PROTOCOL_VERSION, buffer);
    pack_time(now, buffer);

    sicp_iterator = list_iterator_create(sicp_job_list);
    while ((sicp_ptr = (sicp_job_t *) list_next(sicp_iterator))) {
        pack32(sicp_ptr->job_id, buffer);
        pack16(sicp_ptr->job_state, buffer);
    }
    list_iterator_destroy(sicp_iterator);
    pthread_mutex_unlock(&sicp_lock);

    old_file = xstrdup(slurmctld_conf.state_save_location);
    xstrcat(old_file, "/sicp_state.old");
    reg_file = xstrdup(slurmctld_conf.state_save_location);
    xstrcat(reg_file, "/sicp_state");
    new_file = xstrdup(slurmctld_conf.state_save_location);
    xstrcat(new_file, "/sicp_state.new");

    lock_state_files();
    log_fd = creat(new_file, 0600);
    if (log_fd < 0) {
        error("Can't save state, create file %s error %m",
              new_file);
        error_code = errno;
    } else {
        int pos = 0, nwrite, amount, rc;
        char *data;

        fd_set_close_on_exec(log_fd);
        nwrite = get_buf_offset(buffer);
        data = (char *)get_buf_data(buffer);
        while (nwrite > 0) {
            amount = write(log_fd, &data[pos], nwrite);
            if ((amount < 0) && (errno != EINTR)) {
                error("Error writing file %s, %m", new_file);
                error_code = errno;
                break;
            }
            nwrite -= amount;
            pos    += amount;
        }

        rc = fsync_and_close(log_fd, "sicp");
        if (rc && !error_code)
            error_code = rc;
    }
    if (error_code) {
        (void) unlink(new_file);
    } else {			/* file shuffle */
        (void) unlink(old_file);
        if (link(reg_file, old_file))
            debug4("unable to create link for %s -> %s: %m",
                   reg_file, old_file);
        (void) unlink(reg_file);
        if (link(new_file, reg_file))
            debug4("unable to create link for %s -> %s: %m",
                   new_file, reg_file);
        (void) unlink(new_file);
    }
    xfree(old_file);
    xfree(reg_file);
    xfree(new_file);
    unlock_state_files();

    free_buf(buffer);
}
Beispiel #22
0
/* We handle both verify and extend with the same function as they
 * are very similiar.
 *
 * note: here we need to have the LOG file name, not signature!
 */
static void
verify(char *name)
{
	FILE *logfp = NULL, *sigfp = NULL, *nsigfp = NULL;
	block_sig_t *bs = NULL;
	gtfile gf;
	uint8_t bHasRecHashes, bHasIntermedHashes;
	uint8_t bInBlock;
	int r = 0;
	char sigfname[4096];
	char oldsigfname[4096];
	char nsigfname[4096];
	gterrctx_t ectx;
	int bInitDone = 0;
	
	if(!strcmp(name, "-")) {
		fprintf(stderr, "%s mode cannot work on stdin\n",
			mode == MD_VERIFY ? "verify" : "extend");
		goto err;
	} else {
		snprintf(sigfname, sizeof(sigfname), "%s.gtsig", name);
		sigfname[sizeof(sigfname)-1] = '\0';
		if((logfp = fopen(name, "r")) == NULL) {
			perror(name);
			goto err;
		}
		if((sigfp = fopen(sigfname, "r")) == NULL) {
			perror(sigfname);
			goto err;
		}
		if(mode == MD_EXTEND) {
			snprintf(nsigfname, sizeof(nsigfname), "%s.gtsig.new", name);
			nsigfname[sizeof(nsigfname)-1] = '\0';
			if((nsigfp = fopen(nsigfname, "w")) == NULL) {
				perror(nsigfname);
				goto err;
			}
			snprintf(oldsigfname, sizeof(oldsigfname),
			         "%s.gtsig.old", name);
			oldsigfname[sizeof(oldsigfname)-1] = '\0';
		}
	}

	rsgtInit("rsyslog rsgtutil " VERSION);
	rsgt_errctxInit(&ectx);
	bInitDone = 1;
	ectx.verbose = verbose;
	ectx.fp = stderr;
	ectx.filename = strdup(sigfname);

	if((r = rsgt_chkFileHdr(sigfp, "LOGSIG10")) != 0) goto done;
	if(mode == MD_EXTEND) {
		if(fwrite("LOGSIG10", 8, 1, nsigfp) != 1) {
			perror(nsigfname);
			r = RSGTE_IO;
			goto done;
		}
	}
	gf = rsgt_vrfyConstruct_gf();
	if(gf == NULL) {
		fprintf(stderr, "error initializing signature file structure\n");
		goto done;
	}

	bInBlock = 0;
	ectx.blkNum = 0;
	ectx.recNumInFile = 0;

	while(!feof(logfp)) {
		if(bInBlock == 0) {
			if(bs != NULL)
				rsgt_objfree(0x0902, bs);
			if((r = rsgt_getBlockParams(sigfp, 1, &bs, &bHasRecHashes,
							&bHasIntermedHashes)) != 0) {
				if(ectx.blkNum == 0) {
					fprintf(stderr, "EOF before finding any signature block - "
						"is the file still open and being written to?\n");
				} else {
					if(verbose)
						fprintf(stderr, "EOF after signature block %lld\n",
							(long long unsigned) ectx.blkNum);
				}
				goto done;
			}
			rsgt_vrfyBlkInit(gf, bs, bHasRecHashes, bHasIntermedHashes);
			ectx.recNum = 0;
			++ectx.blkNum;
		}
		++ectx.recNum, ++ectx.recNumInFile;
		if((r = doVerifyRec(logfp, sigfp, nsigfp, bs, gf, &ectx, bInBlock)) != 0)
			goto done;
		if(ectx.recNum == bs->recCount) {
			if((r = verifyBLOCK_SIG(bs, gf, sigfp, nsigfp, 
			    (mode == MD_EXTEND) ? 1 : 0, &ectx)) != 0)
				goto done;
			bInBlock = 0;
		} else	bInBlock = 1;
	}
done:
	if(r != RSGTE_EOF)
		goto err;

	/* Make sure we've reached the end of file in both log and signature file */
	if (fgetc(logfp) != EOF) {
		fprintf(stderr, "There are unsigned records in the end of log.\n");
		fprintf(stderr, "Last signed record: %s\n", ectx.errRec);
		r = RSGTE_END_OF_SIG;
		goto err;
	}
	if (fgetc(sigfp) != EOF) {
		fprintf(stderr, "There are records missing from the end of the log file.\n");
		r = RSGTE_END_OF_LOG;
		goto err;
	}


	fclose(logfp); logfp = NULL;
	fclose(sigfp); sigfp = NULL;
	if(nsigfp != NULL) {
		fclose(nsigfp); nsigfp = NULL;
	}

	/* everything went fine, so we rename files if we updated them */
	if(mode == MD_EXTEND) {
		if(unlink(oldsigfname) != 0) {
			if(errno != ENOENT) {
				perror("unlink oldsig");
				r = RSGTE_IO;
				goto err;
			}
		}
		if(link(sigfname, oldsigfname) != 0) {
			perror("link oldsig");
			r = RSGTE_IO;
			goto err;
		}
		if(unlink(sigfname) != 0) {
			perror("unlink cursig");
			r = RSGTE_IO;
			goto err;
		}
		if(link(nsigfname, sigfname) != 0) {
			perror("link  newsig");
			fprintf(stderr, "WARNING: current sig file has been "
			        "renamed to %s - you need to manually recover "
				"it.\n", oldsigfname);
			r = RSGTE_IO;
			goto err;
		}
		if(unlink(nsigfname) != 0) {
			perror("unlink newsig");
			fprintf(stderr, "WARNING: current sig file has been "
			        "renamed to %s - you need to manually recover "
				"it.\n", oldsigfname);
			r = RSGTE_IO;
			goto err;
		}
	}
	rsgtExit();
	rsgt_errctxExit(&ectx);
	return;

err:
	if(r != 0)
		fprintf(stderr, "error %d (%s) processing file %s\n",
			r, RSGTE2String(r), name);
	if(logfp != NULL)
		fclose(logfp);
	if(sigfp != NULL)
		fclose(sigfp);
	if(nsigfp != NULL) {
		fclose(nsigfp);
		unlink(nsigfname);
	}
	if(bInitDone) {
		rsgtExit();
		rsgt_errctxExit(&ectx);
	}
}
Beispiel #23
0
/* output must be a file, which is a (compressed) tar file, of the file denoted by "file", without any of its
   directory paths etc etc */
static void create_fullfile(struct file *file)
{
	char *origin;
	char *tarname = NULL;
	char *rename_source = NULL;
	char *rename_target = NULL;
	char *rename_tmpdir = NULL;
	int ret;
	struct stat sbuf;
	char *empty, *indir, *outdir;
	char *param1, *param2;

	if (file->is_deleted) {
		return; /* file got deleted -> by definition we cannot tar it up */
	}

	empty = config_empty_dir();
	indir = config_image_base();
	outdir = config_output_dir();

	string_or_die(&tarname, "%s/%i/files/%s.tar", outdir, file->last_change, file->hash);
	if (access(tarname, R_OK) == 0) {
		/* output file already exists...done */
		free(tarname);
		return;
	}
	free(tarname);
	//printf("%s was missing\n", file->hash);

	string_or_die(&origin, "%s/%i/full/%s", indir, file->last_change, file->filename);
	if (lstat(origin, &sbuf) < 0) {
		/* no input file: means earlier phase of update creation failed */
		LOG(NULL, "Failed to stat", "%s: %s", origin, strerror(errno));
		assert(0);
	}

	if (file->is_dir) { /* directories are easy */
		char *tmp1, *tmp2, *dir, *base;

		tmp1 = strdup(origin);
		assert(tmp1);
		base = basename(tmp1);

		tmp2 = strdup(origin);
		assert(tmp2);
		dir = dirname(tmp2);

		string_or_die(&rename_tmpdir, "%s/XXXXXX", outdir);
		if (!mkdtemp(rename_tmpdir)) {
			LOG(NULL, "Failed to create temporary directory for %s move", origin);
			assert(0);
		}

		string_or_die(&param1, "--exclude=%s/?*", base);
		string_or_die(&param2, "./%s", base);
		char *const tarcfcmd[] = { TAR_COMMAND, "-C", dir, TAR_PERM_ATTR_ARGS_STRLIST, "-cf", "-", param1, param2, NULL };
		char *const tarxfcmd[] = { TAR_COMMAND, "-C", rename_tmpdir, TAR_PERM_ATTR_ARGS_STRLIST, "-xf", "-", NULL };

		int tarcmdresult = system_argv_pipe(tarcfcmd, tarxfcmd);
		if (tarcmdresult != 0) {
			LOG(NULL, "Tar command for copying directory full file failed with code %d", tarcmdresult);
			assert(0);
		}
		free(param1);
		free(param2);

		string_or_die(&rename_source, "%s/%s", rename_tmpdir, base);
		string_or_die(&rename_target, "%s/%s", rename_tmpdir, file->hash);
		if (rename(rename_source, rename_target)) {
			LOG(NULL, "rename failed for %s to %s", rename_source, rename_target);
			assert(0);
		}
		free(rename_source);

		/* for a directory file, tar up simply with gzip */
		string_or_die(&param1, "%s/%i/files/%s.tar", outdir, file->last_change, file->hash);
		char *const tarcmd[] = { TAR_COMMAND, "-C", rename_tmpdir, TAR_PERM_ATTR_ARGS_STRLIST, "-zcf", param1, file->hash, NULL };

		if (system_argv(tarcmd) != 0) {
			assert(0);
		}
		free(param1);

		if (rmdir(rename_target)) {
			LOG(NULL, "rmdir failed for %s", rename_target);
		}
		free(rename_target);
		if (rmdir(rename_tmpdir)) {
			LOG(NULL, "rmdir failed for %s", rename_tmpdir);
		}
		free(rename_tmpdir);

		free(tmp1);
		free(tmp2);
	} else { /* files are more complex */
		char *gzfile = NULL, *bzfile = NULL, *xzfile = NULL;
		char *tempfile;
		uint64_t gz_size = LONG_MAX, bz_size = LONG_MAX, xz_size = LONG_MAX;

		/* step 1: hardlink the guy to an empty directory with the hash as the filename */
		string_or_die(&tempfile, "%s/%s", empty, file->hash);
		if (link(origin, tempfile) < 0) {
			LOG(NULL, "hardlink failed", "%s due to %s (%s -> %s)", file->filename, strerror(errno), origin, tempfile);
			char *const argv[] = { "cp", "-a", origin, tempfile, NULL };
			if (system_argv(argv) != 0) {
				assert(0);
			}
		}

		/* step 2a: tar it with each compression type  */
		// lzma
		string_or_die(&param1, "--directory=%s", empty);
		string_or_die(&param2, "%s/%i/files/%s.tar.xz", outdir, file->last_change, file->hash);
		char *const tarlzmacmd[] = { TAR_COMMAND, param1, TAR_PERM_ATTR_ARGS_STRLIST, "-Jcf", param2, file->hash, NULL };

		if (system_argv(tarlzmacmd) != 0) {
			assert(0);
		}
		free(param1);
		free(param2);

		// gzip
		string_or_die(&param1, "--directory=%s", empty);
		string_or_die(&param2, "%s/%i/files/%s.tar.gz", outdir, file->last_change, file->hash);
		char *const targzipcmd[] = { TAR_COMMAND, param1, TAR_PERM_ATTR_ARGS_STRLIST, "-zcf", param2, file->hash, NULL };

		if (system_argv(targzipcmd) != 0) {
			assert(0);
		}
		free(param1);
		free(param2);

#ifdef SWUPD_WITH_BZIP2
		string_or_die(&param1, "--directory=%s", empty);
		string_or_die(&param2, "%s/%i/files/%s.tar.bz2", outdir, file->last_change, file->hash);
		char *const tarbzip2cmd[] = { TAR_COMMAND, param1, TAR_PERM_ATTR_ARGS_STRLIST, "-jcf", param2, file->hash, NULL };

		if (system_argv(tarbzip2cmd) != 0) {
			assert(0);
		}
		free(param1);
		free(param2);

#endif

		/* step 2b: pick the smallest of the three compression formats */
		string_or_die(&gzfile, "%s/%i/files/%s.tar.gz", outdir, file->last_change, file->hash);
		if (stat(gzfile, &sbuf) == 0) {
			gz_size = sbuf.st_size;
		}
		string_or_die(&bzfile, "%s/%i/files/%s.tar.bz2", outdir, file->last_change, file->hash);
		if (stat(bzfile, &sbuf) == 0) {
			bz_size = sbuf.st_size;
		}
		string_or_die(&xzfile, "%s/%i/files/%s.tar.xz", outdir, file->last_change, file->hash);
		if (stat(xzfile, &sbuf) == 0) {
			xz_size = sbuf.st_size;
		}
		string_or_die(&tarname, "%s/%i/files/%s.tar", outdir, file->last_change, file->hash);
		if (gz_size <= xz_size && gz_size <= bz_size) {
			ret = rename(gzfile, tarname);
		} else if (xz_size <= bz_size) {
			ret = rename(xzfile, tarname);
		} else {
			ret = rename(bzfile, tarname);
		}
		if (ret != 0) {
			LOG(file, "post-tar rename failed", "ret=%d", ret);
		}
		unlink(bzfile);
		unlink(xzfile);
		unlink(gzfile);
		free(bzfile);
		free(xzfile);
		free(gzfile);
		free(tarname);

		/* step 3: remove the hardlink */
		unlink(tempfile);
		free(tempfile);
	}

	free(indir);
	free(outdir);
	free(empty);
	free(origin);
}
void GL::Program::initFromSource(const char * data)
{
	if (!m_Manager)
		throw std::runtime_error("resource manager is not available.");

	std::vector<std::string> lines;

	for (const char * p = data; ; )
	{
		const char * end = strchr(p, '\n');
		if (end)
		{
			size_t length = end - p;
			while (length > 0 && iswhite(p[length - 1]))
				--length;
			lines.push_back(std::string(p, length) + "\n");
			p = end + 1;
		}
		else
		{
			size_t length = strlen(p);
			while (length > 0 && iswhite(p[length - 1]))
				--length;
			lines.push_back(std::string(p, length) + "\n");
			break;
		}
	}

	std::vector<const char *> vertex;
	std::vector<const char *> fragment;

	vertex.reserve(lines.size());
	fragment.reserve(lines.size());

	bool hasVertex = false, hasFragment = 0;
	Enum type = GL::NONE;
	for (std::vector<std::string>::const_iterator it = lines.begin(); it != lines.end(); ++it)
	{
		if (it->c_str()[0] != '%')
		{
			vertex.push_back(type == GL::NONE || type == GL::VERTEX_SHADER ? it->c_str() : "");
			fragment.push_back(type == GL::NONE || type == GL::FRAGMENT_SHADER ? it->c_str() : "");
		}
		else
		{
			const std::string & str = *it;
			const char * file = nullptr;

			vertex.push_back("");
			fragment.push_back("");

			if (str.length() >= 7 && !memcmp(str.c_str(), "%vertex", 7))
			{
				type = GL::VERTEX_SHADER;
				file = str.c_str() + 7;
			}
			else if (str.length() >= 9 && !memcmp(str.c_str(), "%fragment", 9))
			{
				type = GL::FRAGMENT_SHADER;
				file = str.c_str() + 9;
			}
			else
			{
				std::stringstream ss;
				ss << "invalid directive '" << str << "' in the vertex program.";
				throw std::runtime_error(ss.str());
			}

			if (file)
			{
				while (iswhite(*file))
					++file;
				if (!*file)
					file = nullptr;
			}

			if (!file)
			{
				if (type == GL::VERTEX_SHADER)
					hasVertex = true;
				else if (type == GL::FRAGMENT_SHADER)
					hasFragment = true;
			}
			else
			{
				std::string filename(file);
				if (filename.length() > 0 && filename[filename.length() - 1] == '\n')
					filename.resize(filename.length() - 1);
				attachShader(m_Manager->getShader(type, filename));
			}
		}
	}

	if (hasVertex)
	{
		ShaderPtr shader = m_Manager->createShader(GL::VERTEX_SHADER);
		shader->initFromSource(vertex);
		attachShader(shader);
	}

	if (hasFragment)
	{
		ShaderPtr shader = m_Manager->createShader(GL::FRAGMENT_SHADER);
		shader->initFromSource(fragment);
		attachShader(shader);
	}

	link();
}
Beispiel #25
0
extern int archive_write_file(Buf buffer, char *cluster_name,
			      time_t period_start, time_t period_end,
			      char *arch_dir, char *arch_type,
			      uint32_t archive_period)
{
	int fd = 0;
	int rc = SLURM_SUCCESS;
	char *old_file = NULL, *new_file = NULL, *reg_file = NULL;
	static int high_buffer_size = (1024 * 1024);
	static pthread_mutex_t local_file_lock = PTHREAD_MUTEX_INITIALIZER;

	xassert(buffer);

	slurm_mutex_lock(&local_file_lock);

	/* write the buffer to file */
	reg_file = _make_archive_name(period_start, period_end,
				      cluster_name, arch_dir,
				      arch_type, archive_period);

	debug("Storing %s archive for %s at %s",
	      arch_type, cluster_name, reg_file);
	old_file = xstrdup_printf("%s.old", reg_file);
	new_file = xstrdup_printf("%s.new", reg_file);

	fd = creat(new_file, 0600);
	if (fd < 0) {
		error("Can't save archive, create file %s error %m", new_file);
		rc = SLURM_ERROR;
	} else {
		int pos = 0, nwrite = get_buf_offset(buffer), amount;
		char *data = (char *)get_buf_data(buffer);
		high_buffer_size = MAX(nwrite, high_buffer_size);
		while (nwrite > 0) {
			amount = write(fd, &data[pos], nwrite);
			if ((amount < 0) && (errno != EINTR)) {
				error("Error writing file %s, %m", new_file);
				rc = SLURM_ERROR;
				break;
			}
			nwrite -= amount;
			pos    += amount;
		}
		fsync(fd);
		close(fd);
	}

	if (rc)
		(void) unlink(new_file);
	else {			/* file shuffle */
		int ign;	/* avoid warning */
		(void) unlink(old_file);
		ign =  link(reg_file, old_file);
		(void) unlink(reg_file);
		ign =  link(new_file, reg_file);
		(void) unlink(new_file);
	}
	xfree(old_file);
	xfree(reg_file);
	xfree(new_file);
	slurm_mutex_unlock(&local_file_lock);

	return rc;
}
Beispiel #26
0
void
_nc_write_entry(TERMTYPE * const tp)
{
    struct stat statbuf;
    char name_list[MAX_TERMINFO_LENGTH];
    char *first_name, *other_names;
    char *ptr;
    char filename[PATH_MAX];
    char linkname[PATH_MAX];
#if USE_SYMLINKS
    char symlinkname[PATH_MAX];
#if !HAVE_LINK
#undef HAVE_LINK
#define HAVE_LINK 1
#endif
#endif /* USE_SYMLINKS */
    static int call_count;
    static time_t start_time;	/* time at start of writes */

    if (call_count++ == 0) {
	start_time = 0;
    }

    (void) strcpy(name_list, tp->term_names);
    DEBUG(7, ("Name list = '%s'", name_list));

    first_name = name_list;

    ptr = &name_list[strlen(name_list) - 1];
    other_names = ptr + 1;

    while (ptr > name_list && *ptr != '|')
	ptr--;

    if (ptr != name_list) {
	*ptr = '\0';

	for (ptr = name_list; *ptr != '\0' && *ptr != '|'; ptr++)
	    continue;

	if (*ptr == '\0')
	    other_names = ptr;
	else {
	    *ptr = '\0';
	    other_names = ptr + 1;
	}
    }

    DEBUG(7, ("First name = '%s'", first_name));
    DEBUG(7, ("Other names = '%s'", other_names));

    _nc_set_type(first_name);

    if (strlen(first_name) > sizeof(filename) - 3)
	_nc_warning("terminal name too long.");

    sprintf(filename, "%c/%s", first_name[0], first_name);

    /*
     * Has this primary name been written since the first call to
     * write_entry()?  If so, the newer write will step on the older,
     * so warn the user.
     */
    if (start_time > 0 &&
	stat(filename, &statbuf) >= 0
	&& statbuf.st_mtime >= start_time) {
	_nc_warning("name multiply defined.");
    }

    check_writeable(first_name[0]);
    write_file(filename, tp);

    if (start_time == 0) {
	if (stat(filename, &statbuf) < 0
	    || (start_time = statbuf.st_mtime) == 0) {
	    _nc_syserr_abort("error obtaining time from %s/%s",
			     _nc_tic_dir(0), filename);
	}
    }
    while (*other_names != '\0') {
	ptr = other_names++;
	while (*other_names != '|' && *other_names != '\0')
	    other_names++;

	if (*other_names != '\0')
	    *(other_names++) = '\0';

	if (strlen(ptr) > sizeof(linkname) - 3) {
	    _nc_warning("terminal alias %s too long.", ptr);
	    continue;
	}
	if (strchr(ptr, '/') != 0) {
	    _nc_warning("cannot link alias %s.", ptr);
	    continue;
	}

	check_writeable(ptr[0]);
	sprintf(linkname, "%c/%s", ptr[0], ptr);

	if (strcmp(filename, linkname) == 0) {
	    _nc_warning("self-synonym ignored");
	} else if (stat(linkname, &statbuf) >= 0 &&
		   statbuf.st_mtime < start_time) {
	    _nc_warning("alias %s multiply defined.", ptr);
	} else if (_nc_access(linkname, W_OK) == 0)
#if HAVE_LINK
	{
	    int code;
#if USE_SYMLINKS
	    strcpy(symlinkname, "../");
	    strncat(symlinkname, filename, sizeof(symlinkname) - 4);
	    symlinkname[sizeof(symlinkname) - 1] = '\0';
#endif /* USE_SYMLINKS */
#if HAVE_REMOVE
	    code = remove(linkname);
#else
	    code = unlink(linkname);
#endif
	    if (code != 0 && errno == ENOENT)
		code = 0;
#if USE_SYMLINKS
	    if (symlink(symlinkname, linkname) < 0)
#else
	    if (link(filename, linkname) < 0)
#endif /* USE_SYMLINKS */
	    {
		/*
		 * If there wasn't anything there, and we cannot
		 * link to the target because it is the same as the
		 * target, then the source must be on a filesystem
		 * that uses caseless filenames, such as Win32, etc.
		 */
		if (code == 0 && errno == EEXIST)
		    _nc_warning("can't link %s to %s", filename, linkname);
		else if (code == 0 && (errno == EPERM || errno == ENOENT))
		    write_file(linkname, tp);
		else {
#if MIXEDCASE_FILENAMES
		    _nc_syserr_abort("can't link %s to %s", filename, linkname);
#else
		    _nc_warning("can't link %s to %s (errno=%d)", filename,
				linkname, errno);
#endif
		}
	    } else {
		DEBUG(1, ("Linked %s", linkname));
	    }
	}
#else /* just make copies */
	    write_file(linkname, tp);
#endif /* HAVE_LINK */
    }
}
Beispiel #27
0
void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex)
{
    int dst = instruction[1].u.operand;
    int callee = instruction[2].u.operand;
    int argCount = instruction[3].u.operand;
    int registerOffset = instruction[4].u.operand;

    // Handle eval
    JmpSrc wasEval;
    if (opcodeID == op_call_eval) {
        emitGetVirtualRegister(callee, X86::ecx, i);
        compileOpCallEvalSetupArgs(instruction);

        emitCTICall(i, Interpreter::cti_op_call_eval);
        __ cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::eax);
        wasEval = __ jne();
    }

    // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
    // This deliberately leaves the callee in ecx, used when setting up the stack frame below
    emitGetVirtualRegister(callee, X86::ecx, i);
    __ cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::ecx);
    JmpDst addressOfLinkedFunctionCheck = __ label();
    m_slowCases.append(SlowCaseEntry(__ jne(), i));
    ASSERT(X86Assembler::getDifferenceBetweenLabels(addressOfLinkedFunctionCheck, __ label()) == repatchOffsetOpCallCall);
    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;

    // The following is the fast case, only used whan a callee can be linked.

    // In the case of OpConstruct, call out to a cti_ function to create the new object.
    if (opcodeID == op_construct) {
        int proto = instruction[5].u.operand;
        int thisRegister = instruction[6].u.operand;

        emitPutCTIArg(X86::ecx, 0);
        emitPutCTIArgFromVirtualRegister(proto, 12, X86::eax);
        emitCTICall(i, Interpreter::cti_op_construct_JSConstruct);
        emitPutVirtualRegister(thisRegister);
        emitGetVirtualRegister(callee, X86::ecx, i);
    }

    // Fast version of stack frame initialization, directly relative to edi.
    // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
    __ movl_i32m(asInteger(noValue()), (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register)), X86::edi);
    __ movl_rm(X86::ecx, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register)), X86::edi);
    __ movl_mr(FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node), X86::ecx, X86::edx); // newScopeChain
    __ movl_i32m(argCount, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register)), X86::edi);
    __ movl_rm(X86::edi, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register)), X86::edi);
    __ movl_rm(X86::edx, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)), X86::edi);
    __ addl_i32r(registerOffset * sizeof(Register), X86::edi);

    // Call to the callee
    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(i, reinterpret_cast<void*>(unreachable));
    
    if (opcodeID == op_call_eval)
        __ link(wasEval, __ label());

    // Put the return value in dst. In the interpreter, op_ret does this.
    emitPutVirtualRegister(dst);

#if ENABLE(CODEBLOCK_SAMPLING)
        __ movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_interpreter->sampler()->codeBlockSlot());
#endif
}
Beispiel #28
0
void CPU::exec16(const Instruction16 &insn) {
	switch(insn.OP) {
		case 0x00:
				switch(insn.rform.func4) {
					// nop!
					case 0x00: /* noting */ break;
					// mlfh! rDg0, rAg1
					case 0x01: g0[insn.rform.rD] = g1[insn.rform.rA]; break;
					// mhfl! rDg1, rAg0
					case 0x02: g1[insn.rform.rD] = g0[insn.rform.rA]; break;
					// mv! rDg0, rAg0
					case 0x03: g0[insn.rform.rD] = g0[insn.rform.rA]; break;
					// br{cond}! rAg0
					case 0x04: if(conditional(insn.rform.rD)) branch(g0[insn.rform.rA] - 2, false); break;
					// t{cond}!
					case 0x05: T = conditional(insn.rform.rD); break;

					default: debugDump();
				}
			break;
		case 0x01: {
				uint32_t &rA = g0[insn.rform.rA];
//				uint32_t &rD = g0[insn.rform.rD];
				switch(insn.rform.func4) {
					// mtce{lh}! rA
					case 0x00:
							switch(insn.rform.rD) {
								case 0x00: CEL = rA; break;
								case 0x01: CEH = rA; break;
							}
						break;
					// mfce{lh}! rA
					case 0x01:
							switch(insn.rform.rD) {
								case 0x00: rA = CEL; break;
								case 0x01: rA = CEH; break;
							}
						break;

					default: debugDump();
				}
			} break;
		case 0x02: {
				uint32_t &rA = g0[insn.rform.rA];
				uint32_t &rD = g0[insn.rform.rD];
				uint32_t &rAh = g0[insn.rhform.rA];
				uint32_t &rDh = g[insn.rhform.H][insn.rhform.rD];
				switch(insn.rform.func4) {
					// add! rDg0, rAg0
					case 0x00: rD = add(rD, rA, true); break;
					// sub! rDg0, rAg0
					case 0x01: rD = sub(rD, rA, true); break;
					// neg! rDg0, rAg0
					case 0x02: rD = sub(0, rA, true); break;
					// cmp! rDg0, rAg0
					case 0x03: sub(rD, rA, true); break;
					// and! rDg0, rAg0
					case 0x04: rD = bit_and(rD, rA, true); break;
					// or! rDg0, rAg0
					case 0x05: rD = bit_or(rD, rA, true); break;
					// not! rDg0, rAg0
					case 0x06: rD = bit_xor(rA, ~0, true); break;
					// xor! rDg0, rAg0
					case 0x07: rD = bit_xor(rD, rA, true); break;
					// lw! rDg0, [rAg0]
					case 0x08: rD = miu.readU32(rA); break;
					// lh! rDg0, [rAg0]
					case 0x09: rD = sign_extend(miu.readU16(rA), 16); break;
					// pop! rDgh, [rAg0]
					case 0x0A: rDh = miu.readU32(rAh); rAh += 4; break;
					// lbu! rDg0, [rAg0]
					case 0x0B: rD = miu.readU8(rA); break;
					// sw! rDg0, [rAg0]
					case 0x0C: miu.writeU32(rA, rD); break;
					// sh! rDg0, [rAg0]
					case 0x0D: miu.writeU16(rA, rD); break;
					// push! rDgh, [rAg0]
					case 0x0E: miu.writeU32(rAh -= 4, rDh); break;
					// sb! rDg0, [rAg0]
					case 0x0F: miu.writeU8(rA, rD); break;
				}
			} break;
		case 0x03: {
				// j[l]! imm11
				if(insn.jform.LK)
					link();

				pc &= 0xFFFFF000;
				pc |= (insn.jform.Disp11 << 1) - 2;
			} break;
		case 0x04: {
				// b{cond}! imm8
				if(conditional(insn.bxform.EC))
					pc += (sign_extend(insn.bxform.Imm8, 8) << 1) - 2;
			} break;
		case 0x05:
				// ldiu! imm8
				g0[insn.iform2.rD] = insn.iform2.Imm8;
			break;
		case 0x06: {
				uint32_t &rD = g0[insn.iform1.rD];
				uint32_t imm = 1 << insn.iform1.Imm5;
				switch(insn.iform1.func3) {
					// srli! rD, imm5
					case 0x03: rD = srl(rD, insn.iform1.Imm5, true); break;
					// bitclr! rD, imm5
					case 0x04: rD = bit_and(rD, ~imm, true); break;
					// bitset! rD, imm5
					case 0x05: rD = bit_or(rD, imm, true); break;
					// bittst! rD, imm5
					case 0x06: bit_and(rD, imm, true); break;

					default: debugDump();
				}
			} break;
		case 0x07: {
				uint32_t &rD = g0[insn.iform1.rD];
				uint32_t imm = insn.iform1.Imm5 << 2;
				switch(insn.iform1.func3) {
					// lwp! rDg0, imm
					case 0x00: rD = miu.readU32(r2 + imm); break;
					// lbup! rDg0, imm
					case 0x01: rD = miu.readU8(r2 + imm); break;

					// lhp! rDg0, imm
					case 0x03: rD = sign_extend(miu.readU8(r2 + imm), 16); break;
					// swp! rDg0, imm
					case 0x04: miu.writeU32(r2 + imm, rD); break;
					// shp! rDg0, imm
					case 0x05: miu.writeU16(r2 + imm, rD); break;

					// sbp! rDg0, imm
					case 0x07: miu.writeU32(r2 + imm, rD); break;

					default: debugDump();
				}
			} break;
		default: debugDump();
	}
}
Beispiel #29
0
int
anruf( header_p sys, header_p ich, int lmodem, int tries )
{
	char dialstr[80];
	char lockname[FILENAME_MAX];
	header_p p;
	char *name, *pw;
	const char **v;
	int i, err;
	int dial_cnt = 1;

	/* fuer Janus */
	char *arcer=NULL, *arcerin=NULL, *transfer=NULL, *domain;
	header_p t, d;
	int netcall_error;
	char filename[FILENAME_MAX];
	char tmpname[FILENAME_MAX];
	char outname[FILENAME_MAX];
	char inname[FILENAME_MAX];
	char sysname[FILENAME_MAX];
	struct stat st;
	/* ende fuer Janus */

	t = find(HD_ARCEROUT, sys);
	if (!t) {
		newlog(ERRLOG,
			"Kein ausgehender Packer definiert");
		return 1;
	}
	arcer = t->text;
	strlwr(arcer);

	t = find(HD_ARCERIN, sys);
	if (!t) {
		newlog(ERRLOG,
			"Kein eingehender Packer definiert");
		return 1;
	}
	arcerin = t->text;
	strlwr(arcerin);

	t = find(HD_PROTO, sys);
	if (!t) {
		newlog(ERRLOG,
			"Kein Uebertragungsprotokoll definiert");
		return 1;
	}
	transfer = t->text;
	strlwr(transfer);

	name = NULL;
	p = find(HD_SYS, ich);
	if (p) name = p->text;

	pw = NULL;
	p = find(HD_PASSWD, sys);
	if (p) pw = p->text;

	p = find(HD_X_CALL, sys);
	if (!p) {
		fprintf(stderr, "Welches Netcall-Verfahren????\n");
		exit(20);
	}
	for (i = 0, v = verf; *v; i++, v++)
		if (stricmp(*v, p->text) == 0)
			break;
	if (!*v) return 1;

	if (i < ZCONNECT) {
		t = find(HD_SYS, sys);
		if (!t) {
			newlog(ERRLOG,
				"Illegale Systemdatei: Kein " HN_SYS
				": Header oder falscher Name: %s", filename);
			return 1;
		}
		d = find(HD_DOMAIN, sys);
		if (!d) {
			newlog(ERRLOG,
				"Illegale Systemdatei: Kein " HN_DOMAIN
				": Header: %s", filename);
			return 1;
		}

		for (domain = strtok(d->text, " ;,:");
				domain;
				domain = strtok(NULL, " ;,:")) {
			sprintf(sysname, "%s.%s", t->text, domain);
			strlwr(sysname);
			sprintf(tmpname, "%s/%s", netcalldir, sysname);
			newlog(logname,
				"Suche Verzeichnis, versuche %s...", tmpname);
			if (access(tmpname, R_OK|X_OK) == 0)
				break;
		}

		if(access(tmpname, R_OK|X_OK)) {
			/* Problem: temp. Verzeichnis nicht zu haben */
			newlog(logname,
				"Problem beim Netcall: Verzeichnis "
				"nicht gefunden");
			return 1;
		}
	}

	/* ##### HIER WIRD ANGEWAEHLT ##### */
	p = find(HD_TEL, sys);
	while(tries) {
		if(!p) p = find(HD_TEL, sys);
		make_dialstr(dialstr, sizeof(dialstr), p->text);

		fprintf(stderr, "%3d. Anwahlversuch (noch %d): %-.25s\n",
			dial_cnt++, tries, dialstr);                     

		if (redial(dialstr, lmodem, 1) != 0 ) {
			tries--;
			p = p->other;
		} else {
			/* connect */
			break;
		}
	}

	set_local(lmodem, 0);
	time(&online_start);

	if (i < ZCONNECT) {
		if (name) dfree(name);
		name = dstrdup(boxstat.boxname);
		strupr(name);
#ifdef ENABLE_CAPS_IN_PASSWORD
		strupr(pw);
#endif
	}
	if(login(lmodem, i, name, pw)) return 0;

	if (i < ZCONNECT) { /* JANUS */
		int have_file = 0;

		netcall_error = 0;

		if ( janus_wait(lmodem) != 0 )
			return 0;

		sprintf(tmpname, "%s/%s.%d.dir", netcalldir, sysname, getpid());
		mkdir(tmpname, 0755);
		chdir(tmpname);
		/* outname: ausgehendes Archiv
		 * filename: */
		sprintf(outname, "%s/caller.%s", tmpname, arcer);
		sprintf(filename, "%s/%s.%s", netcalldir, sysname, arcer);
		sprintf(lockname, "%s/%s/" PREARC_LOCK, netcalldir, sysname);
		if (access(filename, R_OK) != 0) {
			FILE *f;
			if(access(filename, F_OK) == 0) {
				newlog(ERRLOG,
					"Leerer Puffer, weil keine Erlaubnis "
					"zum Lesen von %s: %s",
					outname, strerror(errno));
			}

			f = fopen(outname, "wb");
			if (!f) {
				newlog(ERRLOG,
					"Kann Netcall %s nicht erzeugen: %s",
					outname, strerror(errno));
				fclose(deblogfile);
				return 1;
			}
			fputs("\r\n", f);
			fclose(f);
		} else { /* can read filename */
			if (waitnolock(lockname, 180)) {
				fclose(deblogfile);
				newlog(OUTGOING, "System %s Prearc LOCK: %s",
					sysname, lockname );
				return 1;
			}
			fprintf(stderr, "Link: %s -> %s\n",
				filename, outname);
			if(link(filename, outname)) {
				fclose(deblogfile);
				newlog(ERRLOG,
					"Linken: %s -> %s fehlgeschlagen: %s",
					filename, outname, strerror(errno));
				netcall_error = 1;
				goto finish;
			}
			have_file = 1;
		}
		sprintf(inname, "called.%s", arcer);

		st.st_size = 0;
		if(stat(outname, &st)) {
			fprintf(stderr,
				"Zugriff auf %s fehlgeschlagen: %s\n",
				outname, strerror(errno));
			netcall_error = 1;
			goto finish;
		}

		newlog(logname, "Sende %s (%ld Bytes) per %s",
		       outname, (long)st.st_size, transfer);

		err = sendfile(transfer, outname);
		if (err) {
			newlog(logname,
				"Versand der Daten fehlgeschlagen");
			netcall_error = 1;
			goto finish;
		}

		newlog(logname, "Empfange mit %s", transfer);
		if (recvfile(transfer, inname)) {
			newlog(logname,
				"Empfang der Daten fehlgeschlagen");
			netcall_error = 1;
			goto finish;
		}
		st.st_size = 0;
		if(stat(inname, &st)) {
			newlog(logname,
				"Zugriff auf %s fehlgeschlagen: %s",
				inname, strerror(errno));
		}
		newlog(logname, "%ld Bytes empfangen", (long)st.st_size);


	finish:

		/* Fertig, Modem auflegen */
		signal(SIGHUP, SIG_IGN);
		fclose(stdin);
		fclose(stdout);
		hayes_hangup(lmodem); DMLOG("hayes hangup modem");
		hangup(lmodem); DMLOG("hangup modem");
		anrufdauer();

		restore_linesettings(lmodem);
		DMLOG("restoring modem parameters");
		close(lmodem); lmodem=-1; DMLOG("close modem");
		/* neuer stdin */
		fopen("/dev/null", "r");
		/* stderr wird in stdout kopiert */
		dup2(fileno(stderr),fileno(stdout));

		if(!netcall_error) {
			/* Netcall war erfolgreich, also Daten loeschen */
		if(have_file) {
			/* Backups von Nullpuffern sind
			   uninteressant */
			backup3(backoutdir,filename,sysname,arcer);
		}
		/* das ist nur ein Link, den putzen wir weg */
		if ( unlink(outname)) {
			newlog(ERRLOG,
			       "Loeschen von %s fehlgeschlagen: %s",
			       outname, strerror(errno));
		}

		fclose(deblogfile);

		/*
		 * Und empfangene Daten (im Hintergrund) einlesen,
		 * das Modem wird sofort wieder freigegeben.
		 */
		switch(fork()) {
		case -1:
			{ /* cannot fork */
				perror("forking import");
				newlog(ERRLOG,
				       "Forken des Importteils "
				       "fehlgeschlagen: %s",
				       strerror(errno));
				break;
			}
		case 0:
			{
				/* Ich bin child */
				deblogfile=fopen("/tmp/import.deblogfile", "a");
				DMLOG("child forked");
				import_all(arcerin, sysname);
				chdir ("/");
				if(rmdir(tmpname)) {
					newlog(ERRLOG,
						"Loeschen von %s "
						"fehlgeschlagen: %s",
						tmpname, strerror(errno));
				}
				fclose(deblogfile);
				exit(0);
			}
		default: /* parent */
			break;
		}
		}
		return(1);

	} else {
		/* ZCONNECT */

		system_master(ich, sys);
		if (auflegen) return 1;
		bereitstellen();
		files = 1;
		senden_queue = todo;
		todo = NULL;
		while (!auflegen) {
			datei_master(ich, sys);
		}
		anrufdauer();
		close(lmodem); DMLOG("close modem");
		aufraeumen();
		exit (0);
	}

	return 1;
}
Beispiel #30
0
int
main(int argc, char **argv)
{
	struct passwd *pw;
	struct group *gptr;
	char *arg, *cp;
	char buf[MAXPATHLEN];
	int i, f, ch;
	struct stat stb;

	/*
	 * Simulate setuid daemon w/ PRIV_END called.
	 * We don't want lpr to actually be setuid daemon since that
	 * requires that the lpr binary be owned by user daemon, which
	 * is potentially unsafe.
	 */
	if ((pw = getpwuid(DEFUID)) == NULL)
		errx(1, "daemon uid (%u) not in password file", DEFUID);
	effective_uid = pw->pw_uid;
	real_uid = getuid();
	effective_gid = pw->pw_gid;
	real_gid = getgid();
	setresgid(real_gid, real_gid, effective_gid);
	setresuid(real_uid, real_uid, effective_uid);

	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		signal(SIGHUP, cleanup);
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, cleanup);
	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
		signal(SIGQUIT, cleanup);
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
		signal(SIGTERM, cleanup);

	gethostname(host, sizeof (host));
	openlog("lpr", 0, LOG_LPR);

	while ((ch = getopt(argc, argv,
	    ":#:1:2:3:4:C:J:P:T:U:cdfghi:lmnpqrstvw:")) != -1) {
		switch (ch) {

		case '#':		/* n copies */
			if (isdigit(*optarg)) {
				i = atoi(optarg);
				if (i > 0)
					ncopies = i;
			}

		case '4':		/* troff fonts */
		case '3':
		case '2':
		case '1':
			fonts[ch - '1'] = optarg;
			break;

		case 'C':		/* classification spec */
			hdr++;
			class = optarg;
			break;

		case 'J':		/* job name */
			hdr++;
			jobname = optarg;
			break;

		case 'P':		/* specifiy printer name */
			printer = optarg;
			break;

		case 'T':		/* pr's title line */
			title = optarg;
			break;

		case 'U':		/* user name */
			hdr++;
			person = optarg;
			break;

		case 'c':		/* print cifplot output */
		case 'd':		/* print tex output (dvi files) */
		case 'g':		/* print graph(1G) output */
		case 'l':		/* literal output */
		case 'n':		/* print ditroff output */
		case 'p':		/* print using ``pr'' */
		case 't':		/* print troff output (cat files) */
		case 'v':		/* print vplot output */
			format = ch;
			break;

		case 'f':		/* print fortran output */
			format = 'r';
			break;

		case 'h':		/* toggle want of header page */
			hdr = !hdr;
			break;

		case 'i':		/* indent output */
			iflag++;
			indent = atoi(optarg);
			if (indent < 0)
				indent = 8;
			break;

		case 'm':		/* send mail when done */
			mailflg++;
			break;

		case 'q':		/* just q job */
			qflag++;
			break;

		case 'r':		/* remove file when done */
			rflag++;
			break;

		case 's':		/* try to link files */
			sflag++;
			break;

		case 'w':		/* versatec page width */
			width = optarg;
			break;

		case ':':               /* catch "missing argument" error */
			if (optopt == 'i') {
				iflag++; /* -i without args is valid */
				indent = 8;
			} else
				usage();
			break;

		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
		printer = DEFLP;
	chkprinter(printer);
	if (SC && ncopies > 1)
		errx(1, "multiple copies are not allowed");
	if (MC > 0 && ncopies > MC)
		errx(1, "only %ld copies are allowed", MC);
	/*
	 * Get the identity of the person doing the lpr using the same
	 * algorithm as lprm. 
	 */
	if (real_uid != DU || person == NULL) {
		if ((pw = getpwuid(real_uid)) == NULL)
			errx(1, "Who are you?");
		if ((person = strdup(pw->pw_name)) == NULL)
			err(1, NULL);
	}
	/*
	 * Check for restricted group access.
	 */
	if (RG != NULL && real_uid != DU) {
		if ((gptr = getgrnam(RG)) == NULL)
			errx(1, "Restricted group specified incorrectly");
		if (gptr->gr_gid != getgid()) {
			while (*gptr->gr_mem != NULL) {
				if ((strcmp(person, *gptr->gr_mem)) == 0)
					break;
				gptr->gr_mem++;
			}
			if (*gptr->gr_mem == NULL)
				errx(1, "Not a member of the restricted group");
		}
	}
	/*
	 * Check to make sure queuing is enabled if real_uid is not root.
	 */
	(void)snprintf(buf, sizeof(buf), "%s/%s", SD, LO);
	if (real_uid && stat(buf, &stb) == 0 && (stb.st_mode & 010))
		errx(1, "Printer queue is disabled");
	/*
	 * Initialize the control file.
	 */
	mktemps();
	tfd = nfile(tfname);
	card('H', host);
	card('P', person);
	if (hdr) {
		if (jobname == NULL) {
			if (argc == 0)
				jobname = "stdin";
			else
				jobname = (arg = strrchr(argv[0], '/')) ?
				    arg + 1 : argv[0];
		}
		card('J', jobname);
		card('C', class);
		if (!SH)
			card('L', person);
	}
	if (iflag)
		card('I', itoa(indent));
	if (mailflg)
		card('M', person);
	if (format == 't' || format == 'n' || format == 'd')
		for (i = 0; i < 4; i++)
			if (fonts[i] != NULL)
				card('1'+i, fonts[i]);
	if (width != NULL)
		card('W', width);

	/*
	 * Read the files and spool them.
	 */
	if (argc == 0)
		copy(0, " ");
	else while (argc--) {
		if (argv[0][0] == '-' && argv[0][1] == '\0') {
			/* use stdin */
			copy(0, " ");
			argv++;
			continue;
		}
		if ((f = test(arg = *argv++)) < 0)
			continue;	/* file unreasonable */

		if (sflag && (cp = linked(arg)) != NULL) {
			(void)snprintf(buf, sizeof(buf), "%d %d",
			    statb.st_dev, statb.st_ino);
			card('S', buf);
			if (format == 'p')
				card('T', title ? title : arg);
			for (i = 0; i < ncopies; i++)
				card(format, &dfname[inchar-2]);
			card('U', &dfname[inchar-2]);
			if (f)
				card('U', cp);
			card('N', arg);
			dfname[inchar]++;
			nact++;
			continue;
		}
		if (sflag)
			warnx("%s: not linked, copying instead", arg);
		if ((i = safe_open(arg, O_RDONLY, 0)) < 0)
			warn("%s", arg);
		else {
			copy(i, arg);
			(void)close(i);
			if (f && unlink(arg) < 0)
				warnx("%s: not removed", arg);
		}
	}

	if (nact) {
		(void)close(tfd);
		tfname[inchar]--;
		/*
		 * Touch the control file to fix position in the queue.
		 */
		PRIV_START;
		if ((tfd = safe_open(tfname, O_RDWR|O_NOFOLLOW, 0)) >= 0) {
			char c;

			if (read(tfd, &c, 1) == 1 &&
			    lseek(tfd, (off_t)0, SEEK_SET) == 0 &&
			    write(tfd, &c, 1) != 1) {
				warn("%s", tfname);
				tfname[inchar]++;
				cleanup(0);
			}
			(void)close(tfd);
		}
		if (link(tfname, cfname) < 0) {
			warn("cannot rename %s", cfname);
			tfname[inchar]++;
			cleanup(0);
		}
		unlink(tfname);
		PRIV_END;
		if (qflag)		/* just q things up */
			exit(0);
		if (!startdaemon(printer))
			printf("jobs queued, but cannot start daemon.\n");
		exit(0);
	}
	cleanup(0);
	return (1);
	/* NOTREACHED */
}