Beispiel #1
0
void
include_start(char *file)
{
	char		*path;
	FILE		*f;
	struct stat	 sb;

	if (*file == '\0')
		yyerror("invalid include file");

	if ((f = fopen(file, "r")) == NULL) {
		xasprintf(&path, "%s/%s", xdirname(conf.conf_file), file);
		if ((f = fopen(path, "r")) == NULL)
			yyerror("%s: %s", path, strerror(errno));
		xfree(file);
	} else
		path = file;

	if (fstat(fileno(f), &sb) != 0)
		yyerror("%s: %s", path, strerror(errno));
	if (geteuid() != 0 && (sb.st_mode & (S_IROTH|S_IWOTH)) != 0)
		log_warnx("%s: world readable or writable", path);

	ARRAY_ADD(&parse_filestack, parse_file);
	parse_file = xmalloc(sizeof *parse_file);
	parse_file->f = f;
	parse_file->line = 1;
	parse_file->path = path;

	log_debug2("including file %s", parse_file->path);
}
Beispiel #2
0
int pkg_dest_init(pkg_dest_t * dest, const char *name, const char *root_dir)
{
    char *status_file_dir;

    dest->name = xstrdup(name);

    /* Guarantee that dest->root_dir ends with a '/' */
    if (root_dir[strlen(root_dir) - 1] == '/') {
        dest->root_dir = xstrdup(root_dir);
    } else {
        sprintf_alloc(&dest->root_dir, "%s/", root_dir);
    }
    file_mkdir_hier(dest->root_dir, 0755);

    sprintf_alloc(&dest->info_dir, "%s/%s", dest->root_dir,
                  opkg_config->info_dir);
    file_mkdir_hier(dest->info_dir, 0755);

    sprintf_alloc(&dest->status_file_name, "%s/%s", dest->root_dir,
                  opkg_config->status_file);

    /* Ensure that the directory in which we will create the status file exists.
     */
    status_file_dir = xdirname(dest->status_file_name);
    file_mkdir_hier(status_file_dir, 0755);
    free(status_file_dir);

    return 0;
}
Beispiel #3
0
int file_mkdir_hier(const char *path, long mode)
{
    struct stat st;
    int r;

    r = stat(path, &st);
    if (r < 0 && errno == ENOENT) {
        int status;
        char *parent;

        parent = xdirname(path);
        status = file_mkdir_hier(parent, mode | 0300);
        free(parent);

        if (status < 0)
            return -1;

        r = mkdir(path, 0777);
        if (r < 0) {
            opkg_perror(ERROR, "Cannot create directory `%s'", path);
            return -1;
        }

        if (mode != -1) {
            r = chmod(path, mode);
            if (r < 0) {
                opkg_perror(ERROR, "Cannot set permissions of directory `%s'",
                            path);
                return -1;
            }
        }
    }

    return 0;
}
Beispiel #4
0
static void rmfiles (char *prefix)
{
#ifdef _WIN32
    /* Win32 doesn't have POSIX dirent functions.  */
    WIN32_FIND_DATA ffd;
    HANDLE hnd;
    int go_on;
    string temp = concat (prefix, "*");
    string directory = xdirname (prefix);

    pushd (directory);
    hnd = FindFirstFile(temp, &ffd);
    go_on = (hnd != INVALID_HANDLE_VALUE);
    while (go_on) {
        /* FIXME: can this remove read-only files also, like rm -f does?  */
        DeleteFile(ffd.cFileName);
        go_on = (FindNextFile(hnd, &ffd) == TRUE);
    }
    FindClose(hnd);
    free(temp);
    popd ();
#else  /* not _WIN32 */
    DIR *dp;
    struct dirent *de;
    int temp_len = strlen (prefix);
    string directory = "./";
    const_string base = xbasename (prefix);

    /* Copy the directory part of PREFIX with the trailing slash, if any.  */
    if (base != prefix)
    {
        directory = (string) xmalloc (base - prefix + 1);
        directory[0] = '\0';
        strncat (directory, prefix, base - prefix);
    }

    /* Find matching files and delete them.  */
    if ((dp = opendir (directory)) != 0) {
        while ((de = readdir (dp)) != 0)
        {
            string found = concat (directory, de->d_name);

            if (FILESTRNCASEEQ (found, prefix, temp_len))
                /* On POSIX-compliant systems, including DJGPP, this will also
                   remove read-only files and empty directories, like rm -f does.  */
                if (remove (found))
                    perror (found);
            free (found);
        }
    }
#endif /* not _WIN32 */
}
Beispiel #5
0
// Compute the current prefix.
void set_current_prefix()
{
  char *pathextstr;
  curr_prefix = new char[path_name_max()];
  // Obtain the full path of the current binary;
  // using GetModuleFileName on MS-Windows,
  // and searching along PATH on other systems.
#ifdef _WIN32
  int len = GetModuleFileName(0, curr_prefix, path_name_max());
  if (len)
    len = GetShortPathName(curr_prefix, curr_prefix, path_name_max());
# if DEBUG
  fprintf(stderr, "curr_prefix: %s\n", curr_prefix);
# endif /* DEBUG */
#else /* !_WIN32 */
  curr_prefix = searchpath(program_name, getenv("PATH"));
  if (!curr_prefix && !strchr(program_name, '.')) {	// try with extensions
    pathextstr = strsave(getenv("PATHEXT"));
    if (!pathextstr)
      pathextstr = strsave(PATH_EXT);
    curr_prefix = searchpathext(program_name, pathextstr, getenv("PATH"));
    a_delete pathextstr;
  }
  if (!curr_prefix)
    return;
#endif /* !_WIN32 */
  msw2posixpath(curr_prefix);
#if DEBUG
  fprintf(stderr, "curr_prefix: %s\n", curr_prefix);
#endif
  curr_prefix = xdirname(curr_prefix);	// directory of executable
  curr_prefix = xdirname(curr_prefix);	// parent directory of executable
  curr_prefix_len = strlen(curr_prefix);
#if DEBUG
  fprintf(stderr, "curr_prefix: %s\n", curr_prefix);
  fprintf(stderr, "curr_prefix_len: %d\n", curr_prefix_len);
#endif
}
Beispiel #6
0
static void
do_kanji (void) {
    const char **p;

    printf("\nAssuming CP %s 932\n", is_cp932_system ? "is" : "is not");

    for (p = ktab; *p; p++) {
        char *q = to_kanji(*p);
        char *r = xdirname(q);

        printf("%s -> %s + %s\n", *p, from_kanji(r), *p + (xbasename(q)-q));

        free (r);
        free (q);
    }
}
Beispiel #7
0
Datei: file.c Projekt: sctb/em
/*
 * This function performs the details of file writing; writing the file
 * in buffer bp to file fn. Uses the file management routines in the
 * "fileio.c" package. Most of the grief is checking of some sort.
 * You may want to call fupdstat() after using this function.
 */
int
writeout(FILE ** ffp, struct buffer *bp, char *fn)
{
	struct stat	statbuf;
	int	 s;
	char     dp[NFILEN];

	if (stat(fn, &statbuf) == -1 && errno == ENOENT) {
		errno = 0;
		(void)xdirname(dp, fn, sizeof(dp));
		(void)strlcat(dp, "/", sizeof(dp));
		if (access(dp, W_OK) && errno == EACCES) {
			dobeep();
			ewprintf("Directory %s write-protected", dp);
			return (FIOERR);
		} else if (errno == ENOENT) {
   			dobeep();
			ewprintf("%s: no such directory", dp);
			return (FIOERR);
		}
        }
	/* open writes message */
	if ((s = ffwopen(ffp, fn, bp)) != FIOSUC)
		return (FALSE);
	s = ffputbuf(*ffp, bp);
	if (s == FIOSUC) {
		/* no write error */
		s = ffclose(*ffp, bp);
		if (s == FIOSUC)
			ewprintf("Wrote %s", fn);
	} else {
		/* print a message indicating write error */
		(void)ffclose(*ffp, bp);
		dobeep();
		ewprintf("Unable to write %s", fn);
	}
	return (s == FIOSUC);
}
Beispiel #8
0
int rfs_op_unlink(char *path) {
	redisReply *rr;
	int ret = -ENOENT;
	char * _dirname;

	ret = rfs_op_exists(path);
	if(ret < 0) return ret;

	rr = redisCommand(dfs.redis.rc, "DEL %s:%s", dfs.redis.ns, path);
	if(rr)
		freeReplyObject(rr);

	ret = 0;

	_dirname = xdirname(path);
	if(_dirname) {
		rr = redisCommand(dfs.redis.rc, "HDEL %s:%s:%s", dfs.redis.ns, _dirname, path);
		if(rr)
			freeReplyObject(rr);
	}

	return ret;
}
Beispiel #9
0
int main(int argc, char **argv)
{
    const char **p;
    kpathsea kpse = kpathsea_new();

    kpathsea_set_program_name (kpse, argv[0], NULL);

    printf("\n%s: name -> xdirname(name) + xbasename(name)\n\n",
           kpse->invocation_short_name);

    for (p = tab; *p; p++) {
        char *q = xdirname(*p);

        printf("%s -> %s + %s\n", *p, q, xbasename(*p));
        free (q);
    }

#if defined (WIN32)
    kanji_test();
#endif

    return 0;
}
Beispiel #10
0
int rfs_op_create(char * name, mode_t mode, rfs_node_type type) {

	redisReply * rr;
	struct stat st;
	int ret = -EACCES;
	char * _dirname;

	rr = redisCommand(dfs.redis.rc, "EXISTS %s:%s", dfs.redis.ns, name);
	if(!rr) return ret;

	if(rr->type != REDIS_REPLY_INTEGER) {
		freeReplyObject(rr);
		return ret;
	}

	if(rr->integer == 1) {
		return -EEXIST;
	}

	freeReplyObject(rr);

	rr = redisCommand(dfs.redis.rc, "HINCRBY %s:state inode 1", dfs.redis.ns);
	if(!rr) return ret;

	if(rr->type != REDIS_REPLY_INTEGER) {
		xlog("rfs_mkdir", "type=%i", rr->type);
		freeReplyObject(rr);
		return ret;
	}

	memset(&st,0,sizeof(st));
	st.st_ino = rr->integer;
	st.st_mode = mode;

	time(&st.st_atime);
	time(&st.st_mtime);
	time(&st.st_ctime);

	switch(type) {
		case RFS_DIR:
			st.st_mode |= S_IFDIR;
			break;
		case RFS_FILE:
			st.st_mode |= S_IFREG;
			break;
		case RFS_LINK: break;
		case RFS_DEV: break;
		default: break;
	}

	freeReplyObject(rr);

/*
	rr = redisCommand(dfs.redis.rc, "HSET %s:%s _stat %b", dfs.redis.ns, name, &st, sizeof(st));
	freeReplyObject(rr);
*/

	ret = rfs_op_stat(name, &st, RFS_OP_STAT_SET);

	_dirname = xdirname(name);
	if(!_dirname) return 0;

	xlog("create", "%s %s\n", name, _dirname);

	if(!strcmp(name,_dirname)) return 0;

	switch(type) {
		case RFS_DIR: {
			rfs_op_add_directory_to_directory(name, _dirname);
			break;
		}
		case RFS_FILE: {
			rfs_op_add_file_to_directory(name, _dirname);
			break;
		}
		case RFS_LINK: break;
		case RFS_DEV: break;
		default: break;
	}

	return 0;
}
Beispiel #11
0
/* Mail state. Find and read mail file. */
int
fetch_mbox_state_mail(struct account *a, struct fetch_ctx *fctx)
{
	struct fetch_mbox_data		*data = a->data;
	struct mail			*m = fctx->mail;
	struct fetch_mbox_mbox		*fmbox;
	struct fetch_mbox_mail		*aux;
	char				*line, *ptr, *lptr;
	size_t				 llen;
	int				 flushing;

	/* Find current mbox and check for EOF. */
	fmbox = ARRAY_ITEM(&data->fmboxes, data->index);
	if (data->off == fmbox->size) {
		fctx->state = fetch_mbox_state_next;
		return (FETCH_AGAIN);
	}

	/* Open the mail. */
	if (mail_open(m, IO_BLOCKSIZE) != 0) {
		log_warn("%s: failed to create mail", a->name);
		mail_destroy(m);
		return (FETCH_ERROR);
	}

	/* Create aux data. */
	aux = xmalloc(sizeof *aux);
	aux->off = data->off;
	aux->size = 0;
	aux->fmbox = fmbox;
	if (++fmbox->reference == 0)
		fatalx("reference count overflow");
	m->auxdata = aux;
	m->auxfree = fetch_mbox_free;

	/* Tag mail. */
	default_tags(&m->tags, NULL);
	add_tag(&m->tags, "mbox", "%s", xbasename(fmbox->path));
	add_tag(&m->tags, "mbox_path", "%s", xdirname(fmbox->path));
	add_tag(&m->tags, "mbox_file", "%s", fmbox->path);

	/*
	 * We start at a "From " line and include it in the mail (it can be
	 * trimmed later with minimal penalty).
	 */
	flushing = 0;
	for (;;) {
		/* Check for EOF. */
		if (data->off == fmbox->size) {
			aux->size = data->off - aux->off;
			break;
		}

		/* Locate the EOL. */
		line = fmbox->base + data->off;
		ptr = memchr(line, '\n', fmbox->size - data->off);
		if (ptr == NULL) {
			ptr = fmbox->base + fmbox->size;
			data->off = fmbox->size;
		} else
			data->off += ptr - line + 1;

		/* Check if the line is "From ". */
		if (line > fmbox->base &&
		    ptr - line >= 5 && strncmp(line, "From ", 5) == 0) {
			/* End of mail. */
			aux->size = (line - fmbox->base) - aux->off;
			break;
		}

		/* Trim >s from From. */
		if (*line == '>') {
			lptr = line;
			llen = ptr - line;
			while (*lptr == '>' && llen > 0) {
				lptr++;
				llen--;
			}

			if (llen >= 5 && strncmp(lptr, "From ", 5) == 0)
				line++;
		}

		if (flushing)
			continue;
		if (append_line(m, line, ptr - line) != 0) {
			log_warn("%s: failed to resize mail", a->name);
			mail_destroy(m);
			return (FETCH_ERROR);
		}
		if (m->size > conf.max_size)
			flushing = 1;
	}
	fmbox->total++;

	/*
	 * Check if there was a blank line between the mails and remove it if
	 * so.
	 */
	if (aux->size >= 2 &&
	    fmbox->base[aux->off + aux->size - 1] == '\n' &&
	    fmbox->base[aux->off + aux->size - 2] == '\n') {
		aux->size -= 2;
		m->size -= 2;
	}

	return (FETCH_MAIL);
}
Beispiel #12
0
static string
remove_dots P1C(string, dir)
{
#ifdef AMIGA
  return dir;
#else
  string c;
  unsigned len;
  string ret = (string) ""; /* We always reassign.  */
  
  for (c = kpse_filename_component (dir); c;
       c = kpse_filename_component (NULL)) {
    if (STREQ (c, ".")) {
      /* If leading ., replace with cwd.  Else ignore.  */
      if (*ret == 0) {
        ret = xgetcwd ();
      }

    } else if (STREQ (c, "..")) {
      /* If leading .., start with xdirname (cwd).  Else remove last
         component from ret, if any.  */
      if (*ret == 0) {
        string dot = xgetcwd ();
        ret = xdirname (dot);
        free (dot);
      } else {
        unsigned last;
        for (last = strlen (ret);
             last > (NAME_BEGINS_WITH_DEVICE (ret) ? 2 : 0);
             last--) {
          if (IS_DIR_SEP (ret[last - 1])) {
            /* If we have `/../', that's the same as `/'.  */
            if (last > 1) {
              ret[last - 1] = 0;
            }
            break;
          }
        }
      }

    } else {
      /* Not . or ..; just append.  Include a directory separator unless
         our string already ends with one.  This also changes all directory
         separators into the canonical DIR_SEP_STRING.  */
      string temp;
      len = strlen (ret);
      temp = concat3 (ret, ((len > 0 && ret[len - 1] == DIR_SEP)
                            || (NAME_BEGINS_WITH_DEVICE (c) && *ret == 0))
                           ? "" : DIR_SEP_STRING,
                      c);
      if (*ret)
        free (ret);
      ret = temp;
    }
  }
  
  /* Remove a trailing /, just in case it snuck in.  */
  len = strlen (ret);
  if (len > 0 && ret[len - 1] == DIR_SEP) {
    ret[len - 1] = 0;
  }

  return ret;
#endif /* not AMIGA */
}
Beispiel #13
0
int
insertfile(char *fname, char *newname, int replacebuf)
{
	struct buffer	*bp;
	struct line	*lp1, *lp2;
	struct line	*olp;			/* line we started at */
	struct mgwin	*wp;
	int	 nbytes, s, nline = 0, siz, x, x2;
	int	 opos;			/* offset we started at */
	int	 oline;			/* original line number */
	char *dp;

	if (replacebuf == TRUE)
		x = undo_enable(FFRAND, 0);
	else
		x = undo_enabled();

	lp1 = NULL;
	if (line == NULL) {
		line = malloc(NLINE);
		if (line == NULL)
			panic("out of memory");
		linesize = NLINE;
	}

	/* cheap */
	bp = curbp;
	if (newname != NULL) {
		(void)strlcpy(bp->b_fname, newname, sizeof(bp->b_fname));
		dp = xdirname(newname);
		(void)strlcpy(bp->b_cwd, dp, sizeof(bp->b_cwd));
		(void)strlcat(bp->b_cwd, "/", sizeof(bp->b_cwd));
		free(dp);
	}

	/* hard file open */
	if ((s = ffropen(fname, (replacebuf == TRUE) ? bp : NULL)) == FIOERR)
		goto out;
	if (s == FIOFNF) {
		/* file not found */
		if (newname != NULL)
			ewprintf("(New file)");
		else
			ewprintf("(File not found)");
		goto out;
	} else if (s == FIODIR) {
		/* file was a directory */
		if (replacebuf == FALSE) {
			ewprintf("Cannot insert: file is a directory, %s",
			    fname);
			goto cleanup;
		}
		killbuffer(bp);
		if ((bp = dired_(fname)) == NULL)
			return (FALSE);
		undo_enable(FFRAND, x);
		curbp = bp;
		return (showbuffer(bp, curwp, WFFULL | WFMODE));
	} else {
		dp = xdirname(fname);
		(void)strlcpy(bp->b_cwd, dp, sizeof(bp->b_cwd));
		(void)strlcat(bp->b_cwd, "/", sizeof(bp->b_cwd));
		free(dp);
	}
	opos = curwp->w_doto;
	oline = curwp->w_dotline;
	/*
	 * Open a new line at dot and start inserting after it.
	 * We will delete this newline after insertion.
	 * Disable undo, as we create the undo record manually.
	 */
	x2 = undo_enable(FFRAND, 0);
	(void)lnewline();
	olp = lback(curwp->w_dotp);
	undo_enable(FFRAND, x2);

	nline = 0;
	siz = 0;
	while ((s = ffgetline(line, linesize, &nbytes)) != FIOERR) {
retry:
		siz += nbytes + 1;
		switch (s) {
		case FIOSUC:
			/* FALLTHRU */
		case FIOEOF:
			++nline;
			if ((lp1 = lalloc(nbytes)) == NULL) {
				/* keep message on the display */
				s = FIOERR;
				undo_add_insert(olp, opos,
				    siz - nbytes - 1 - 1);
				goto endoffile;
			}
			bcopy(line, &ltext(lp1)[0], nbytes);
			lp2 = lback(curwp->w_dotp);
			lp2->l_fp = lp1;
			lp1->l_fp = curwp->w_dotp;
			lp1->l_bp = lp2;
			curwp->w_dotp->l_bp = lp1;
			if (s == FIOEOF) {
				undo_add_insert(olp, opos, siz - 1);
				goto endoffile;
			}
			break;
		case FIOLONG: {
				/* a line too long to fit in our buffer */
				char	*cp;
				int	newsize;

				newsize = linesize * 2;
				if (newsize < 0 ||
				    (cp = malloc(newsize)) == NULL) {
					ewprintf("Could not allocate %d bytes",
					    newsize);
						s = FIOERR;
						goto endoffile;
				}
				bcopy(line, cp, linesize);
				free(line);
				line = cp;
				s = ffgetline(line + linesize, linesize,
				    &nbytes);
				nbytes += linesize;
				linesize = newsize;
				if (s == FIOERR)
					goto endoffile;
				goto retry;
			}
		default:
			ewprintf("Unknown code %d reading file", s);
			s = FIOERR;
			break;
		}
	}
endoffile:
	/* ignore errors */
	ffclose(NULL);
	/* don't zap an error */
	if (s == FIOEOF) {
		if (nline == 1)
			ewprintf("(Read 1 line)");
		else
			ewprintf("(Read %d lines)", nline);
	}
	/* set mark at the end of the text */
	curwp->w_dotp = curwp->w_markp = lback(curwp->w_dotp);
	curwp->w_marko = llength(curwp->w_markp);
	curwp->w_markline = oline + nline + 1;
	/*
	 * if we are at the end of the file, ldelnewline is a no-op,
	 * but we still need to decrement the line and markline counts
	 * as we've accounted for this fencepost in our arithmetic
	 */
	if (lforw(curwp->w_dotp) == curwp->w_bufp->b_headp) {
		curwp->w_bufp->b_lines--;
		curwp->w_markline--;
	} else
		(void)ldelnewline();
	curwp->w_dotp = olp;
	curwp->w_doto = opos;
	curwp->w_dotline = oline;
	if (olp == curbp->b_headp)
		curwp->w_dotp = lforw(olp);
	if (newname != NULL)
		bp->b_flag |= BFCHG | BFBAK;	/* Need a backup.	 */
	else
		bp->b_flag |= BFCHG;
	/*
	 * If the insert was at the end of buffer, set lp1 to the end of
	 * buffer line, and lp2 to the beginning of the newly inserted text.
	 * (Otherwise lp2 is set to NULL.)  This is used below to set
	 * pointers in other windows correctly if they are also at the end of
	 * buffer.
	 */
	lp1 = bp->b_headp;
	if (curwp->w_markp == lp1) {
		lp2 = curwp->w_dotp;
	} else {
		/* delete extraneous newline */
		(void)ldelnewline();
out:		lp2 = NULL;
	}
	for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
		if (wp->w_bufp == curbp) {
			wp->w_flag |= WFMODE | WFEDIT;
			if (wp != curwp && lp2 != NULL) {
				if (wp->w_dotp == lp1)
					wp->w_dotp = lp2;
				if (wp->w_markp == lp1)
					wp->w_markp = lp2;
				if (wp->w_linep == lp1)
					wp->w_linep = lp2;
			}
		}
	}
	bp->b_lines += nline;
cleanup:
	undo_enable(FFRAND, x);

	/* return FALSE if error */
	return (s != FIOERR);
}
Beispiel #14
0
Datei: file.c Projekt: sctb/em
/*
 * Read the file "fname" into the current buffer.  Make all of the text
 * in the buffer go away, after checking for unsaved changes.  This is
 * called by the "read" command, the "visit" command, and the mainline
 * (for "mg file").
 */
int
readin(char *fname)
{
	struct mgwin	*wp;
	struct stat	 statbuf;
	int	 status, ro = FALSE;
	char	 dp[NFILEN];

	/* might be old */
	if (bclear(curbp) != TRUE)
		return (TRUE);
	/* Clear readonly. May be set by autoexec path */
	curbp->b_flag &= ~BFREADONLY;
	if ((status = insertfile(fname, fname, TRUE)) != TRUE) {
		dobeep();
		ewprintf("File is not readable: %s", fname);
		return (FALSE);
	}

	for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
		if (wp->w_bufp == curbp) {
			wp->w_dotp = wp->w_linep = bfirstlp(curbp);
			wp->w_doto = 0;
			wp->w_markp = NULL;
			wp->w_marko = 0;
		}
	}

	/* no change */
	curbp->b_flag &= ~BFCHG;

	/*
	 * Set the buffer READONLY flag if any of following are true:
	 *   1. file is a directory.
	 *   2. file is read-only.
	 *   3. file doesn't exist and directory is read-only.
	 */
	if (fisdir(fname) == TRUE) {
		ro = TRUE;
	} else if ((access(fname, W_OK) == -1)) {
		if (errno != ENOENT) {
			ro = TRUE;
		} else if (errno == ENOENT) {
			(void)xdirname(dp, fname, sizeof(dp));
			(void)strlcat(dp, "/", sizeof(dp));

			/* Missing directory; keep buffer rw, like emacs */
			if (stat(dp, &statbuf) == -1 && errno == ENOENT) {
				if (eyorn("Missing directory, create") == TRUE)
					(void)do_makedir(dp);
			} else if (access(dp, W_OK) == -1 && errno == EACCES) {
				ewprintf("File not found and directory"
				    " write-protected");
				ro = TRUE;
			}
		}
	}
	if (ro == TRUE)
		curbp->b_flag |= BFREADONLY;

	if (startrow) {
		gotoline(FFARG, startrow);
		startrow = 0;
	}

	undo_add_modified();
	return (status);
}
Beispiel #15
0
static string
selfdir P1C(const_string, argv0)
{
  string ret = NULL;
  string self = NULL;
  
  if (kpse_absolute_p (argv0, true)) {
    self = xstrdup (argv0);
  } else {
#ifdef AMIGA
#include <dos.h>
#include <proto/dos.h>
#include <proto/exec.h>
    BPTR lock;
    struct DosLibrary *DOSBase
      = (struct DosLibrary *) OpenLibrary ("dos.library", 0L);
    assert (DOSBase);

    self = xmalloc (BUFSIZ);
    lock = findpath (argv0);
    if (lock != ((BPTR) -1)) {
      if (getpath (lock, self) == -1) {
        *self = '\0';
      } else {
        strcat (self,DIR_SEP_STRING);
        strcat (self,argv0); 
      }
      UnLock (lock);
    }
    CloseLibrary((struct Library *) DOSBase);
#else /* not AMIGA */
    string elt;
    struct stat s;

    /* Have to check PATH.  But don't call kpse_path_search since we don't
       want to search any ls-R's or do anything special with //'s.  */
    for (elt = kpse_path_element (getenv ("PATH")); !self && elt;
         elt = kpse_path_element (NULL)) {
      string name;
      
      /* UNIX tradition interprets the empty path element as "." */
      if (*elt == 0) elt = ".";
      
      name = concat3 (elt, DIR_SEP_STRING, argv0);

      /* In order to do this perfectly, we'd have to check the owner bits only
         if we are the file owner, and the group bits only if we belong
         to the file group.  That's a lot of work, though, and it's not
         likely that kpathsea will ever be used with a program that's
         only executable by some classes and not others.  See the
         `file_status' function in execute_cmd.c in bash for what's
         necessary if we were to do it right.  */
      if (stat (name, &s) == 0 && s.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
        /* Do not stop at directories. */
        if (!S_ISDIR(s.st_mode)) 
          self = name;
      }
    }
#endif /* not AMIGA */
  }
  
  /* If argv0 is somehow dir/exename, `self' will still be NULL.  */
  if (!self)
    self = concat3 (".", DIR_SEP_STRING, argv0);
    
  ret = xdirname (remove_dots (expand_symlinks (self)));

  free (self);
  
  return ret;
}
Beispiel #16
0
static void
compile_dex_with_dexopt(const char* dex_file_name,
                        const char* odex_file_name)
{
    SCOPED_RESLIST(rl);

    int dex_file = xopen(dex_file_name, O_RDONLY, 0);
    const char* odex_temp_filename = xaprintf(
        "%s.tmp.%s",
        odex_file_name,
        gen_hex_random(ENOUGH_ENTROPY));
    cleanup_commit(cleanup_allocate(), cleanup_tmpfile, odex_temp_filename);
    int odex_temp_file = xopen(odex_temp_filename,
                               O_RDWR | O_CREAT | O_EXCL,
                               0644);

    allow_inherit(dex_file);
    allow_inherit(odex_temp_file);

    struct child_start_info csi = {
        .io[0] = CHILD_IO_DEV_NULL,
        .io[1] = CHILD_IO_PIPE,
        .io[2] = CHILD_IO_DUP_TO_STDOUT,
        .exename = "dexopt",
        .argv = ARGV(
            "dexopt",
            "--zip",
            xaprintf("%d", dex_file),
            xaprintf("%d", odex_temp_file),
            dex_file_name,
            "v=ao=fm=y"),
    };

    struct child* dexopt = child_start(&csi);
    struct growable_buffer output = slurp_fd_buf(dexopt->fd[1]->fd);
    int status = child_status_to_exit_code(child_wait(dexopt));
    if (status != 0)
        die(EINVAL,
            "dexopt failed: %s",
            massage_output_buf(output));

    xrename(odex_temp_filename, odex_file_name);
}

static void
compile_dex(const char* dex_file_name,
            const char* odex_file_name)
{
    if (api_level() < 21)
        compile_dex_with_dexopt(dex_file_name, odex_file_name);
}

int
rdex_main(const struct cmd_rdex_info* info)
{
    const char* dex_file_name = info->dexfile;
    struct stat dex_stat = xstat(dex_file_name);
    const char* odex_file_name = make_odex_name(dex_file_name);

    bool need_recompile = true;

    struct stat odex_stat;
    if (stat(odex_file_name, &odex_stat) == 0 &&
        dex_stat.st_mtime <= odex_stat.st_mtime)
    {
        need_recompile = false;
    }

    (void) need_recompile;
    (void) odex_file_name;
    (void) compile_dex;

    if (need_recompile)
        compile_dex(dex_file_name, odex_file_name);

    if (setenv("CLASSPATH", dex_file_name, 1) == -1)
        die_errno("setenv");

    if (info->classname[0] == '-')
        die(EINVAL, "class name cannot begin with '-'");

    execvp("app_process",
           (char* const*)
           ARGV_CONCAT(
               ARGV("app_process",
                    xdirname(dex_file_name),
                    info->classname),
               info->args ?: empty_argv));
    die_errno("execvp(\"app_process\", ...");
}
Beispiel #17
0
int
deliver_mbox_deliver(struct deliver_ctx *dctx, struct actitem *ti)
{
    struct account			*a = dctx->account;
    struct mail			*m = dctx->mail;
    struct deliver_mbox_data	*data = ti->data;
    char				*path, *ptr, *lptr, *from = NULL;
    const char			*msg;
    size_t				 len, llen;
    int				 fd, saved_errno;
    FILE				*f;
    gzFile				 gzf;
    long long			 used;
    sigset_t			 set, oset;
    struct stat			 sb;

    f = gzf = NULL;
    fd = -1;

    path = replacepath(&data->path, m->tags, m, &m->rml, dctx->udata->home);
    if (path == NULL || *path == '\0') {
        log_warnx("%s: empty path", a->name);
        goto error;
    }
    if (data->compress) {
        len = strlen(path);
        if (len < 3 || strcmp(path + len - 3, ".gz") != 0) {
            path = xrealloc(path, 1, len + 4);
            strlcat(path, ".gz", len + 4);
        }
    }
    log_debug2("%s: saving to mbox %s", a->name, path);

    /* Save the mbox path. */
    add_tag(&m->tags, "mbox_file", "%s", path);

    /* Check permissions and ownership. */
    if (stat(path, &sb) != 0) {
        if (conf.no_create || errno != ENOENT)
            goto error_log;

        log_debug2("%s: creating %s", a->name, xdirname(path));
        if (xmkpath(xdirname(path), -1, conf.file_group, DIRMODE) != 0)
            goto error_log;
    } else {
        if ((msg = checkmode(&sb, UMASK(FILEMODE))) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
        if ((msg = checkowner(&sb, -1)) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
        if ((msg = checkgroup(&sb, conf.file_group)) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
    }

    /* Create or open the mbox. */
    used = 0;
    do {
        if (conf.no_create)
            fd = openlock(path, O_WRONLY|O_APPEND, conf.lock_types);
        else {
            fd = createlock(path, O_WRONLY|O_APPEND,
                            -1, conf.file_group, FILEMODE, conf.lock_types);
        }
        if (fd == -1 && errno == EEXIST)
            fd = openlock(path, O_WRONLY|O_APPEND, conf.lock_types);
        if (fd == -1) {
            if (errno == EAGAIN) {
                if (locksleep(a->name, path, &used) != 0)
                    goto error;
                continue;
            }
            goto error_log;
        }
    } while (fd < 0);

    /* Open gzFile or FILE * for writing. */
    if (data->compress) {
        if ((gzf = gzdopen(fd, "a")) == NULL) {
            errno = ENOMEM;
            goto error_log;
        }
    } else {
        if ((f = fdopen(fd, "a")) == NULL)
            goto error_log;
    }

    /*
     * mboxes are a pain: if we are interrupted after this we risk
     * having written a partial mail. So, block SIGTERM until we're
     * done.
     */
    sigemptyset(&set);
    sigaddset(&set, SIGTERM);
    if (sigprocmask(SIG_BLOCK, &set, &oset) < 0)
        fatal("sigprocmask failed");

    /* Write the from line. */
    from = make_from(m, dctx->udata->name);
    if (deliver_mbox_write(f, gzf, from, strlen(from)) < 0) {
        xfree(from);
        goto error_unblock;
    }
    if (deliver_mbox_write(f, gzf, "\n", 1) < 0) {
        xfree(from);
        goto error_unblock;
    }
    log_debug3("%s: using from line: %s", a->name, from);
    xfree(from);

    /* Write the mail, escaping from lines. */
    line_init(m, &ptr, &len);
    while (ptr != NULL) {
        if (ptr != m->data) {
            /* Skip leading >s. */
            lptr = ptr;
            llen = len;
            while (*lptr == '>' && llen > 0) {
                lptr++;
                llen--;
            }

            if (llen >= 5 && strncmp(lptr, "From ", 5) == 0) {
                log_debug2("%s: quoting from line: %.*s",
                           a->name, (int) len - 1, ptr);
                if (deliver_mbox_write(f, gzf, ">", 1) < 0)
                    goto error_unblock;
            }
        }

        if (deliver_mbox_write(f, gzf, ptr, len) < 0)
            goto error_unblock;

        line_next(m, &ptr, &len);
    }

    /* Append newlines. */
    if (m->data[m->size - 1] == '\n') {
        if (deliver_mbox_write(f, gzf, "\n", 1) < 0)
            goto error_unblock;
    } else {
        if (deliver_mbox_write(f, gzf, "\n\n", 2) < 0)
            goto error_unblock;
    }

    /* Flush buffers and sync. */
    if (gzf == NULL) {
        if (fflush(f) != 0)
            goto error_unblock;
    } else {
        if (gzflush(gzf, Z_FINISH) != Z_OK) {
            errno = EIO;
            goto error_unblock;
        }
    }
    if (fsync(fd) != 0)
        goto error_unblock;

    if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
        fatal("sigprocmask failed");

    if (gzf != NULL)
        gzclose(gzf);
    if (f != NULL)
        fclose(f);
    closelock(fd, path, conf.lock_types);

    xfree(path);
    return (DELIVER_SUCCESS);

error_unblock:
    saved_errno = errno;
    if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
        fatal("sigprocmask failed");
    errno = saved_errno;

error_log:
    log_warn("%s: %s", a->name, path);

error:
    if (gzf != NULL)
        gzclose(gzf);
    if (f != NULL)
        fclose(f);
    if (fd != -1)
        closelock(fd, path, conf.lock_types);

    if (path != NULL)
        xfree(path);
    return (DELIVER_FAILURE);
}
Beispiel #18
0
void
browse(const char *ipath, const char *ifilter)
{
	int r, fd;
	regex_t re;
	char *newpath;
	struct stat sb;
	char *name, *bin, *dir, *tmp, *run, *env;
	int nowtyping = 0;
    FILE *fp;

	oldpath = NULL;
	path = xstrdup(ipath);
	fltr = xstrdup(ifilter);
begin:
	/* Path and filter should be malloc(3)-ed strings at all times */
	r = populate();
	if (r == -1) {
		if (!nowtyping) {
			printwarn();
			goto nochange;
		}
	}

	for (;;) {
		redraw();

		/* Handle filter-as-you-type mode */
		if (nowtyping)
			goto moretyping;
nochange:
		switch (nextsel(&run, &env)) {
		case SEL_QUIT:
			free(path);
			free(fltr);
			dentfree(dents, n);
			return;
		case SEL_BACK:
			/* There is no going back */
			if (strcmp(path, "/") == 0 ||
			    strcmp(path, ".") == 0 ||
			    strchr(path, '/') == NULL)
				goto nochange;
			dir = xdirname(path);
			if (canopendir(dir) == 0) {
				free(dir);
				printwarn();
				goto nochange;
			}
			/* Save history */
			oldpath = path;
			path = dir;
			/* Reset filter */
			free(fltr);
			fltr = xstrdup(ifilter);
			goto begin;
		case SEL_GOIN:
			/* Cannot descend in empty directories */
			if (n == 0)
				goto nochange;

			name = dents[cur].name;
			newpath = mkpath(path, name);
			DPRINTF_S(newpath);

			/* Get path info */
			fd = open(newpath, O_RDONLY | O_NONBLOCK);
			if (fd == -1) {
				printwarn();
				free(newpath);
				goto nochange;
			}
			r = fstat(fd, &sb);
			if (r == -1) {
				printwarn();
				close(fd);
				free(newpath);
				goto nochange;
			}
			close(fd);
			DPRINTF_U(sb.st_mode);

			switch (sb.st_mode & S_IFMT) {
			case S_IFDIR:
				if (canopendir(newpath) == 0) {
					printwarn();
					free(newpath);
					goto nochange;
				}
				free(path);
				path = newpath;
				/* Reset filter */
				free(fltr);
				fltr = xstrdup(ifilter);
				goto begin;
			case S_IFREG:
				bin = openwith(newpath);
				if (bin == NULL) {
					printmsg("No association");
					free(newpath);
					goto nochange;
				}
				exitcurses();
				spawn(bin, newpath, NULL);
				initcurses();
				free(newpath);
				continue;
			default:
				printmsg("Unsupported file");
				goto nochange;
			}
		case SEL_FLTR:
			/* Read filter */
			printprompt("filter: ");
			tmp = readln();
			if (tmp == NULL)
				tmp = xstrdup(ifilter);
			/* Check and report regex errors */
			r = setfilter(&re, tmp);
			if (r != 0) {
				free(tmp);
				goto nochange;
			}
			free(fltr);
			fltr = tmp;
			DPRINTF_S(fltr);
			/* Save current */
			if (n > 0)
				oldpath = mkpath(path, dents[cur].name);
			goto begin;
		case SEL_TYPE:
			nowtyping = 1;
			tmp = NULL;
moretyping:
			printprompt("type: ");
			if (tmp != NULL)
				printw("%s", tmp);
			r = readmore(&tmp);
			DPRINTF_D(r);
			DPRINTF_S(tmp);
			if (r == 1)
				nowtyping = 0;
			/* Check regex errors */
			if (tmp != NULL) {
				r = setfilter(&re, tmp);
				if (r != 0)
					if (nowtyping) {
						goto moretyping;
					} else {
						free(tmp);
						goto nochange;
					}
			}
			/* Copy or reset filter */
			free(fltr);
			if (tmp != NULL)
				fltr = xstrdup(tmp);
			else
				fltr = xstrdup(ifilter);
			/* Save current */
			if (n > 0)
				oldpath = mkpath(path, dents[cur].name);
			if (!nowtyping)
				free(tmp);
			goto begin;
		case SEL_NEXT:
			if (cur < n - 1)
				cur++;
			break;
		case SEL_PREV:
			if (cur > 0)
				cur--;
			break;
		case SEL_PGDN:
			if (cur < n - 1)
				cur += MIN((LINES - 4) / 2, n - 1 - cur);
			break;
		case SEL_PGUP:
			if (cur > 0)
				cur -= MIN((LINES - 4) / 2, cur);
			break;
		case SEL_HOME:
			cur = 0;
			break;
		case SEL_END:
			cur = n - 1;
			break;
		case SEL_CD:
			/* Read target dir */
			printprompt("chdir: ");
			tmp = readln();
			if (tmp == NULL) {
				clearprompt();
				goto nochange;
			}
			newpath = mkpath(path, tmp);
			free(tmp);
			if (canopendir(newpath) == 0) {
				free(newpath);
				printwarn();
				goto nochange;
			}
			free(path);
			path = newpath;
			free(fltr);
			fltr = xstrdup(ifilter); /* Reset filter */
			DPRINTF_S(path);
			goto begin;
		case SEL_MTIME:
			mtimeorder = !mtimeorder;
			/* Save current */
			if (n > 0)
				oldpath = mkpath(path, dents[cur].name);
			goto begin;
		case SEL_REDRAW:
			/* Save current */
			if (n > 0)
				oldpath = mkpath(path, dents[cur].name);
			goto begin;
		case SEL_RUN:
			run = xgetenv(env, run);
			exitcurses();
			spawn(run, NULL, path);
			initcurses();
			break;
		case SEL_RUNARG:
			name = dents[cur].name;
			run = xgetenv(env, run);
			exitcurses();
			spawn(run, name, path);
			initcurses();
			break;
        case SEL_PRINT:
			name = dents[cur].name;
            fp = fopen("savelist.txt", "a");
            fprintf(fp, "%s/%s\n", path, name);
            fclose(fp);
            break;
		}
		/* Screensaver */
		if (idletimeout != 0 && idle == idletimeout) {
			idle = 0;
			exitcurses();
			spawn(idlecmd, NULL, NULL);
			initcurses();
		}
	}
}
Beispiel #19
0
static void
do_xfer_recv(const struct xfer_opts xfer_opts,
             const char* filename,
             const char* desired_basename,
             int from_peer)
{
    struct xfer_msg statm = recv_xfer_msg(from_peer);
    if (statm.type != XFER_MSG_STAT)
        die(ECOMM, "expected stat msg");

    struct cleanup* error_cl = cleanup_allocate();
    struct stat st;
    const char* parent_directory = NULL;
    const char* rename_to = NULL;
    const char* write_mode = NULL;
    int dest_fd;

    if (stat(filename, &st) == 0) {
        if (S_ISDIR(st.st_mode)) {
            if (desired_basename == NULL)
                die(EISDIR, "\"%s\" is a directory", filename);
            parent_directory = filename;
            filename = xaprintf("%s/%s",
                                parent_directory,
                                desired_basename);
        } else if (S_ISREG(st.st_mode)) {
            if (st.st_nlink > 1)
                write_mode = "inplace";
        } else {
            write_mode = "inplace";
        }
    }

    if (parent_directory == NULL)
        parent_directory = xdirname(filename);

    if (write_mode == NULL)
        write_mode = xfer_opts.write_mode;

    bool atomic;
    bool automatic_mode = false;
    if (write_mode == NULL) {
        automatic_mode = true;
        atomic = true;
    } else if (strcmp(write_mode, "atomic") == 0) {
        atomic = true;
    } else if (strcmp(write_mode, "inplace") == 0) {
        atomic = false;
    } else {
        die(EINVAL, "unknown write mode \"%s\"", write_mode);
    }

    bool regular_file = true;
    bool preallocated = false;
    bool chmod_explicit = false;
    mode_t chmod_explicit_modes = 0;

    if (xfer_opts.preserve) {
        chmod_explicit = true;
        chmod_explicit_modes = statm.u.stat.ugo_bits;
    }

    if (xfer_opts.mode) {
        char* endptr = NULL;
        errno = 0;
        unsigned long omode = strtoul(xfer_opts.mode, &endptr, 8);
        if (errno != 0 || *endptr != '\0' || (omode &~ 0777) != 0)
            die(EINVAL, "invalid mode bits: %s", xfer_opts.mode);
        chmod_explicit = true;
        chmod_explicit_modes = (mode_t) omode;
    }

    mode_t creat_mode = (chmod_explicit_modes ? 0200 : 0666);

    if (atomic) {
        rename_to = filename;
        filename =
            xaprintf("%s.fb-adb-%s",
                     filename,
                     gen_hex_random(ENOUGH_ENTROPY));
        dest_fd = try_xopen(
            filename,
            O_CREAT | O_WRONLY | O_EXCL,
            creat_mode);
        if (dest_fd == -1) {
            if (errno == EACCES && automatic_mode) {
                atomic = false;
                filename = rename_to;
                rename_to = NULL;
            } else {
                die_errno("open(\"%s\")", filename);
            }
        }
    }

    if (!atomic) {
        dest_fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, creat_mode);
        if (!S_ISREG(xfstat(dest_fd).st_mode))
            regular_file = false;
    }

    if (regular_file)
        cleanup_commit(error_cl, unlink_cleanup, filename);

    if (regular_file && statm.u.stat.size > 0)
        preallocated = fallocate_if_supported(
            dest_fd,
            statm.u.stat.size);

    uint64_t total_written = copy_loop_posix_recv(from_peer, dest_fd);

    if (preallocated && total_written < statm.u.stat.size)
        xftruncate(dest_fd, total_written);

    if (xfer_opts.preserve) {
        struct timeval times[2] = {
            { statm.u.stat.atime, statm.u.stat.atime_ns / 1000 },
            { statm.u.stat.mtime, statm.u.stat.mtime_ns / 1000 },
        };
#ifdef HAVE_FUTIMES
        if (futimes(dest_fd, times) == -1)
            die_errno("futimes");
#else
        if (utimes(filename, times) == -1)
            die_errno("times");
#endif
    }

    if (chmod_explicit)
        if (fchmod(dest_fd, chmod_explicit_modes) == -1)
            die_errno("fchmod");

    if (xfer_opts.sync)
        xfsync(dest_fd);

    if (rename_to)
        xrename(filename, rename_to);

    if (xfer_opts.sync)
        xfsync(xopen(parent_directory, O_DIRECTORY|O_RDONLY, 0));

    cleanup_forget(error_cl);
}
Beispiel #20
0
void
kpse_set_program_name P2C(const_string, argv0, const_string, progname)
{
  string ext, sdir, sdir_parent, sdir_grandparent;
  string s = getenv ("KPATHSEA_DEBUG");
#ifdef WIN32
  string debug_output = getenv("KPATHSEA_DEBUG_OUTPUT");
  string append_debug_output = getenv("KPATHSEA_DEBUG_APPEND");
  int err, olderr;
#endif
  
  /* Set debugging stuff first, in case we end up doing debuggable stuff
     during this initialization.  */
  if (s) {
    kpathsea_debug |= atoi (s);
  }

#ifndef HAVE_PROGRAM_INVOCATION_NAME
#if defined(WIN32)
  /* Set various info about user. Among many things,
     ensure that HOME is set. If debug_paths is on, 
     turn on some message if $HOME is not found. */
  if (KPSE_DEBUG_P(KPSE_DEBUG_PATHS)) {
    set_home_warning();
  }
  init_user_info();

  /* redirect stderr to debug_output. Easier to send logfiles. */
  if (debug_output) {
    int flags =  _O_CREAT | _O_TRUNC | _O_RDWR;
    err = -1;
    if (_stricmp(debug_output, "con") == 0
       || _stricmp(debug_output, "con:") == 0) {
      err = _fileno(stdout);
    } else {
      if (append_debug_output) {
        flags =  _O_CREAT | _O_APPEND | _O_WRONLY;
      } else {
        flags =  _O_CREAT | _O_TRUNC | _O_WRONLY;
        xputenv("KPATHSEA_DEBUG_APPEND", "yes");
      }
    }

    if ((err < 0)
        && (err = _open(debug_output, flags, _S_IREAD | _S_IWRITE)) == -1)
    {
      WARNING1("Can't open %s for stderr redirection!\n", debug_output);
      perror(debug_output);
    } else if ((olderr = _dup(fileno(stderr))) == -1) {
      WARNING("Can't dup() stderr!\n");
      close(err);
    } else if (_dup2(err, fileno(stderr)) == -1) {
      WARNING1("Can't redirect stderr to %s!\n", debug_output);
      close(olderr);
      close(err);
    } else {
      close(err);
    }
  }
  /* Win95 always gives the short filename for argv0, not the long one.
     There is only this way to catch it. It makes all the selfdir stuff
     useless for win32. */
  {
    char short_path[PATH_MAX], path[PATH_MAX], *fp;
      
    /* SearchPath() always gives back an absolute directory */
    if (SearchPath(NULL, argv0, ".exe", PATH_MAX, short_path, &fp) == 0)
        FATAL1("Can't determine where the executable %s is.\n", argv0);
    if (!win32_get_long_filename(short_path, path, sizeof(path))) {
        FATAL1("This path points to an invalid file : %s\n", short_path);
    }
    /* slashify the dirname */
    for (fp = path; fp && *fp; fp++)
        if (IS_DIR_SEP(*fp)) *fp = DIR_SEP;
    /* sdir will be the directory of the executable, ie: c:/TeX/bin */
    sdir = xdirname(path);
    program_invocation_name = xstrdup(xbasename(path));
  }

#elif defined(__DJGPP__)

  /* DJGPP programs support long filenames on Windows 95, but ARGV0 there
     is always made with the short 8+3 aliases of all the pathname elements.
     If long names are supported, we need to convert that to a long name.

     All we really need is to call `_truename', but most of the code
     below is required to deal with the special case of networked drives.  */
  if (pathconf (argv0, _PC_NAME_MAX) > 12) {
    char long_progname[PATH_MAX];

    if (_truename (argv0, long_progname)) {
      char *fp;

      if (long_progname[1] != ':') {
	/* A complication: `_truename' returns network-specific string at
	   the beginning of `long_progname' when the program resides on a
	   networked drive, and DOS calls cannot grok such pathnames.  We
	   need to convert the filesystem name back to a drive letter.  */
	char rootname[PATH_MAX], rootdir[4];

	if (argv0[0] && argv0[1] == ':')
	  rootdir[0] = argv0[0]; /* explicit drive in `argv0' */
	else
	  rootdir[0] = getdisk () + 'A';
	rootdir[1] = ':';
	rootdir[2] = '\\';
	rootdir[3] = '\0';
	if (_truename (rootdir, rootname)) {
	  /* Find out where `rootname' ends in `long_progname' and replace
	     it with the drive letter.  */
	  int root_len = strlen (rootname);

 	  if (IS_DIR_SEP (rootname[root_len - 1]))
            root_len--;	/* keep the trailing slash */
	  long_progname[0] = rootdir[0];
	  long_progname[1] = ':';
	  memmove (long_progname + 2, long_progname + root_len,
		   strlen (long_progname + root_len) + 1);
	}
      }

      /* Convert everything to canonical form.  */
      if (long_progname[0] >= 'A' && long_progname[0] <= 'Z')
	long_progname[0] += 'a' - 'A'; /* make drive lower case, for beauty */
      for (fp = long_progname; *fp; fp++)
	if (IS_DIR_SEP (*fp))
	  *fp = DIR_SEP;

      program_invocation_name = xstrdup (long_progname);
    }
    else
      /* If `_truename' failed, God help them, because we won't...  */
      program_invocation_name = xstrdup (argv0);
  }
  else
    program_invocation_name = xstrdup (argv0);

#else /* !WIN32 && !__DJGPP__ */

  program_invocation_name = xstrdup (argv0);

#endif
#endif /* not HAVE_PROGRAM_INVOCATION_NAME */

  /* We need to find SELFAUTOLOC *before* removing the ".exe" suffix from
     the program_name, otherwise the PATH search inside selfdir will fail,
     since `prog' doesn't exists as a file, there's `prog.exe' instead.  */
#ifndef WIN32
  sdir = selfdir (program_invocation_name);
#endif
  /* SELFAUTODIR is actually the parent of the invocation directory,
     and SELFAUTOPARENT the grandparent.  This is how teTeX did it.  */
  xputenv ("SELFAUTOLOC", sdir);
  sdir_parent = xdirname (sdir);
  xputenv ("SELFAUTODIR", sdir_parent);
  sdir_grandparent = xdirname (sdir_parent);
  xputenv ("SELFAUTOPARENT", sdir_grandparent);

  free (sdir);
  free (sdir_parent);
  free (sdir_grandparent);

#ifndef HAVE_PROGRAM_INVOCATION_NAME
  program_invocation_short_name = (string)xbasename (program_invocation_name);
#endif

  if (progname) {
    kpse_program_name = xstrdup (progname);
  } else {
    /* If configured --enable-shared and running from the build directory
       with the wrapper scripts (e.g., for make check), the binaries will
       be named foo.exe instead of foo.  Or possibly if we're running on a
       DOSISH system.  */
    ext = find_suffix (program_invocation_short_name);
    if (ext && FILESTRCASEEQ (ext, "exe")) {
      kpse_program_name = remove_suffix (program_invocation_short_name);
    } else {
      kpse_program_name = xstrdup (program_invocation_short_name);
    }
  }
  xputenv("progname", kpse_program_name);
}