Beispiel #1
0
static void
RenderTextPolled(VG_Text *vt, VG_View *vv)
{
	char val[64], s[VG_TEXT_MAX], *c;
	int argIdx = 0;

	s[0] = '\0';
	for (c = &vt->text[0]; *c != '\0'; ) {
		if (c[0] != '%') {
			val[0] = *c;
			val[1] = '\0';
			Strlcat(s, val, sizeof(s));
			c++;
			continue;
		}
		if (c[1] == '\0' || c[1] == '%') {
			val[0] = '%';
			val[1] = '\0';
			Strlcat(s, val, sizeof(s));
			c+=2;
			continue;
		}
		if ((argIdx+1) >= vt->args->n) {
			AG_FatalError("Argument inconsistency");
		}
		AG_PrintVariable(val, sizeof(val), &vt->args->v[argIdx]);
		Strlcat(s, val, sizeof(s));
		c += vt->argSizes[argIdx++];
	}
	RenderText(vt, s, vv);
}
Beispiel #2
0
static void
FindWidgets(AG_Widget *wid, AG_Tlist *tl, int depth)
{
	char text[AG_TLIST_LABEL_MAX];
	AG_TlistItem *it;
	AG_Widget *widChld;

	Strlcpy(text, OBJECT(wid)->name, sizeof(text));
	if (AG_OfClass(wid, "AG_Widget:AG_Window:*")) {
		AG_Window *win = (AG_Window *)wid;

		Strlcat(text, " (\"", sizeof(text));
		Strlcat(text, win->caption, sizeof(text));
		Strlcat(text, "\")", sizeof(text));
	}
	it = AG_TlistAddPtr(tl, NULL, text, wid);
	it->depth = depth;
	it->cat = "widget";
	
	if (!TAILQ_EMPTY(&OBJECT(wid)->children)) {
		it->flags |= AG_TLIST_HAS_CHILDREN;
	}
	if ((it->flags & AG_TLIST_HAS_CHILDREN) &&
	    AG_TlistVisibleChildren(tl, it)) {
		OBJECT_FOREACH_CHILD(widChld, wid, ag_widget)
			FindWidgets(widChld, tl, depth+1);
	}
}
Beispiel #3
0
Dir* Dir_Open(const char* path)
{
    Dir* dir;
    char filespec[PAL_MAX_PATH_SIZE];
    
    /* Allocate and zero-fill struct */
    dir = (Dir*)PAL_Calloc(1, sizeof(Dir));
    if (!dir)
        return NULL;

    /* Build files spec */
    {
        if (Strlcpy(filespec, path, sizeof(filespec)) >= PAL_MAX_PATH_SIZE)
            return NULL;

        if (Strlcat(filespec, "/*", sizeof(filespec)) >= PAL_MAX_PATH_SIZE)
            return NULL;
    }

    /* Find first file matching the file spec */
    dir->handle = _findfirst(filespec, &dir->fileinfo);
    if (dir->handle == -1)
    {
        PAL_Free(dir);
        return NULL;
    }

    /* Note that readdir() has not been called yet */
    dir->firstTime = 1;

    return dir;
}
Beispiel #4
0
/* Issue a verbose message. */
void
AG_Verbose(const char *fmt, ...)
{
	va_list args;

	if (!agVerbose)
		return;

	va_start(args, fmt);
#ifdef _WIN32
	{
		char path[AG_FILENAME_MAX];
		FILE *f;

		Strlcpy(path, agProgName, sizeof(path));
		Strlcat(path, ".out", sizeof(path));
		if ((f = fopen(path, "a")) != NULL) {
			vfprintf(f, fmt, args);
			fclose(f);
		}
	}
#else
	vprintf(fmt, args);
#endif
	va_end(args);
}
Beispiel #5
0
FMGUI_Dir *
FMGUI_OpenDir(const char *path)
{
	FMGUI_Dir *dir;

	dir = (FMGUI_Dir *) Malloc(sizeof(FMGUI_Dir));
	dir->ents = NULL;
	dir->nents = 0;

#ifdef _WIN32
	{
		char dpath[FMGUI_PATHNAME_MAX];
		HANDLE h;
		WIN32_FIND_DATA fdata;
		DWORD rv;

		Strlcpy(dpath, path, sizeof(dpath));
		Strlcat(dpath, "\\*", sizeof(dpath));
		if ((h = FindFirstFile(dpath, &fdata))==INVALID_HANDLE_VALUE) {
			ReportError1("Invalid file handle (%d)",
			    (int)GetLastError());
			goto fail;
		}
		while (FindNextFile(h, &fdata) != 0) {
			dir->ents = Realloc(dir->ents,
			    (dir->nents+1)*sizeof(char *));
			dir->ents[dir->nents++] = Strdup(fdata.cFileName);
		}
		rv = GetLastError();
		FindClose(h);
		if (rv != ERROR_NO_MORE_FILES) {
			ReportError1("FindNextFileError (%lu)", rv);
			goto fail;
		}
	}
#else /* !_WIN32 */
	{
		DIR *dp;
		struct dirent *dent;
		
		if ((dp = opendir(path)) == NULL) {
			ReportError2("%s: Failed to open directory (%s)",
			    path, strerror(errno));
			goto fail;
		}
		while ((dent = readdir(dp)) != NULL) {
			dir->ents = (char **) Realloc(dir->ents,
			    (dir->nents+1)*sizeof(char *));
			dir->ents[dir->nents++] = strdup(dent->d_name);
		}
		closedir(dp);
	}
#endif /* _WIN32 */

	return (dir);
fail:
	Free(dir);
	return (NULL);
}
Beispiel #6
0
/*
 * Dump the display surface(s) to a jpeg in ~/.appname/screenshot/.
 * It is customary to assign a AG_GlobalKeys(3) shortcut for this function.
 */
void
AG_ViewCapture(void)
{
	AG_Surface *s;
	char *pname;
	char dir[AG_PATHNAME_MAX];
	char file[AG_PATHNAME_MAX];
	Uint seq;

	if (agDriverSw == NULL) {
		Verbose("AG_ViewCapture() is not implemented under "
		        "multiple-window drivers\n");
		return;
	}

	AG_LockVFS(&agDrivers);

	if (AGDRIVER_SW_CLASS(agDriverSw)->videoCapture(agDriverSw, &s) == -1) {
		Verbose("Capture failed: %s\n", AG_GetError());
		goto out;
	}

	/* Save to a new file. */
	AG_GetString(agConfig, "save-path", dir, sizeof(dir));
	Strlcat(dir, AG_PATHSEP, sizeof(dir));
	Strlcat(dir, "screenshot", sizeof(dir));
	if (!AG_FileExists(dir) && AG_MkPath(dir) == -1) {
		Verbose("Capture failed: %s\n", AG_GetError());
		goto out;
	}
	pname = (agProgName != NULL) ? agProgName : "agarapp";
	for (seq = 0; ; seq++) {
		Snprintf(file, sizeof(file), "%s%c%s%u.jpg",
		    dir, AG_PATHSEPCHAR, pname, seq++);
		if (!AG_FileExists(file))
			break;			/* XXX race condition */
	}
	if (AG_SurfaceExportJPEG(s, file) == 0) {
		Verbose("Saved capture to: %s\n", file);
	} else {
		Verbose("Capture failed: %s\n", AG_GetError());
	}
	AG_SurfaceFree(s);
out:
	AG_UnlockVFS(&agDrivers);
}
Beispiel #7
0
int
AG_ConfigInit(AG_Config *cfg, Uint flags)
{
	char path[AG_PATHNAME_MAX], *s;
	AG_User *sysUser;

	AG_ObjectInit(cfg, &agConfigClass);
	AG_ObjectSetName(cfg, "config");
	OBJECT(cfg)->save_pfx = NULL;

	AG_SetInt(cfg, "initial-run", 1);
	AG_SetInt(cfg, "no-confirm-quit", 0);

	if (agProgName != NULL &&
	    (sysUser = AG_GetRealUser()) != NULL) {
		AG_SetString(cfg, "home", sysUser->home);
		AG_SetString(cfg, "tmp-path", sysUser->tmp);

		Strlcpy(path, sysUser->home, sizeof(path));
		Strlcat(path, AG_PATHSEP, sizeof(path));
		Strlcat(path, ".", sizeof(path));
		Strlcat(path, agProgName, sizeof(path));
		AG_SetString(cfg, "save-path", path);

		if (strcmp(DATADIR, "NONE") != 0) {
			AG_PrtString(cfg, "load-path", "%s%s%s",
			    path, AG_PATHSEPMULTI, DATADIR);
		} else {
			AG_SetString(cfg, "load-path", path);
		}
		AG_UserFree(sysUser);
	} else {
		AG_SetString(cfg, "home", "");
		s = (strcmp(DATADIR,"NONE") != 0) ? DATADIR : ".";
		AG_SetString(cfg, "load-path", s);
		AG_SetString(cfg, "save-path", s);
		AG_SetString(cfg, "tmp-path", "tmp");
	}

	if ((flags & AG_CREATE_DATADIR) &&
	    AG_CreateDataDir() == -1) {
		return (-1);
	}
	return (0);
}
Beispiel #8
0
/* Return a string with the available drivers. */
void
AG_ListDriverNames(char *buf, size_t buf_len)
{
	Uint i;

	if (buf_len == 0) {
		return;
	}
	buf[0] = '\0';

	for (i = 0; i < agDriverListSize; i++) {
		AG_DriverClass *drvClass = agDriverList[i];

		Strlcat(buf, drvClass->name, buf_len);
		if (i < agDriverListSize-1)
			Strlcat(buf, " ", buf_len);
	}
}
Beispiel #9
0
void Fatal(const char* file, size_t line, const char* format, ...)
{
    char prefixedFormat[EXECUTOR_BUFFER_SIZE];

#ifdef PEGASUS_DEBUG
    /* Prepend "__FILE__(__LINE__): FATAL: " to format. */

    char lineStr[32];
    Strlcpy(prefixedFormat, file, sizeof(prefixedFormat));
    Strlcat(prefixedFormat, "(", sizeof(prefixedFormat));
    sprintf(lineStr, "%u", (unsigned int)line);
    Strlcat(prefixedFormat, lineStr, sizeof(prefixedFormat));
    Strlcat(prefixedFormat, "): FATAL: ", sizeof(prefixedFormat));
#endif

    Strlcat(prefixedFormat, format, sizeof(prefixedFormat));

    /* Print to syslog. */
    {
        va_list ap;
        char buffer[EXECUTOR_BUFFER_SIZE];

        va_start(ap, format);
        /* Flawfinder: ignore */
        vsprintf(buffer, prefixedFormat, ap);
        va_end(ap);

        syslog(LOG_CRIT, "%s", buffer);
    }

    /* Print to stderr. */
    {
        va_list ap;

        fprintf(stderr, "%s: ", globals.argv[0]);
        va_start(ap, format);
        /* Flawfinder: ignore */
        vfprintf(stderr, prefixedFormat, ap);
        va_end(ap);
        fputc('\n', stderr);
    }

    Exit(1);
}
Beispiel #10
0
const char* MakePath(
    PathID id, 
    char buf[MAX_PATH_SIZE])
{
    const PathEntry* ent = &_entries[id];

    /* Copy prefix */
    if (Strlcpy(buf, GetPrefix(), MAX_PATH_SIZE) >= MAX_PATH_SIZE)
        return NULL;

    /* If running from source directory */
    if (_runningFromSourceDirectory && id == ID_PLUGIN_LIBDIR)
        return buf;

    /* Copy the LHS */
    {
        const char* p;

        /* Skip over "${prefix}" or "${exec_prefix}" */
        {
            p = ent->lhs;

            if (p[0] == '$' && p[1] == '{')
            {
                for (p += 2; *p && *p != '}'; p++)
                    ;

                if (*p == '}')
                    p++;
            }
        }

        if (Strlcat(buf, p, MAX_PATH_SIZE) >= MAX_PATH_SIZE)
            return NULL;
    }

    /* Copy the RHS */
    if (ent->rhs && Strlcat(buf, ent->rhs, MAX_PATH_SIZE) >= MAX_PATH_SIZE)
        return NULL;

    return buf;
}
Beispiel #11
0
static void
exportpath(Char **val)
{
    Char    exppath[BUFSIZ];

    exppath[0] = 0;
    if (val)
	while (*val) {
	    if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZ) {
		(void) fprintf(csherr,
			       "Warning: ridiculously long PATH truncated\n");
		break;
	    }
	    (void) Strlcat(exppath, *val++, sizeof exppath/sizeof(Char));
	    if (*val == 0 || eq(*val, STRRparen))
		break;
	    (void) Strlcat(exppath, STRcolon, sizeof exppath/sizeof(Char));
	}
    Setenv(STRPATH, exppath);
}
Beispiel #12
0
/* Copy the full pathname of a data file to a sized buffer. */
int
AG_ConfigFile(const char *path_key, const char *name, const char *ext,
    char *path, size_t path_len)
{
	char file[AG_PATHNAME_MAX];
	char *dir, *pathp = path;
	int rv;

	AG_GetString(agConfig, path_key, path, path_len);

	for (dir = Strsep(&pathp, AG_PATHSEPMULTI);
	     dir != NULL;
	     dir = Strsep(&pathp, AG_PATHSEPMULTI)) {
		Strlcpy(file, dir, sizeof(file));

		if (name[0] != AG_PATHSEPCHAR) {
			Strlcat(file, AG_PATHSEP, sizeof(file));
		}
		Strlcat(file, name, sizeof(file));
		if (ext != NULL) {
			Strlcat(file, ".", sizeof(file));
			Strlcat(file, ext, sizeof(file));
		}
		if ((rv = AG_FileExists(file)) == 1) {
			if (Strlcpy(path, file, path_len) >= path_len) {
				AG_SetError(_("The search path is too big."));
				return (-1);
			}
			return (0);
		} else if (rv == -1) {
			AG_SetError("%s: %s", file, AG_GetError());
			return (-1);
		}
	}
	AG_GetString(agConfig, path_key, path, path_len);
	AG_SetError(_("Cannot find %s.%s (in <%s>:%s)."), name,
	    (ext != NULL) ? ext : "", path_key, path);
	return (-1);
}
Beispiel #13
0
int Mkdirhier(const char* path_, int mode)
{
    char path[PAL_MAX_PATH_SIZE];
    char buf[PAL_MAX_PATH_SIZE];
    char* p;
    char* context = NULL;

    /* Make a complete copy of the path (that we can destroy) */
    if (Strlcpy(path, path_, sizeof(path)) >= sizeof(path))
        return -1;

    buf[0] = '\0';

    for (p = Strtok(path, "/", &context); p; p = Strtok(NULL, "/", &context))
    {
#if defined(CONFIG_OS_WINDOWS)
        /* Skip drive letters (on Windows) */
        if (p == path && isalpha((unsigned char)p[0]) && p[1] == ':' && p[2] == '\0')
        {
            Strlcat(buf, p, sizeof(buf));
            continue;
        }
#endif

        /* Concatenate next component */
        Strlcat(buf, "/", sizeof(buf));
        Strlcat(buf, p, sizeof(buf));

        /* Create directory if it does not already exist */
        if (!Isdir(buf))
        {
            if (Mkdir(buf, mode) != 0)
                return -1;
        }
    }

    return 0;
}
Beispiel #14
0
int JoinPath(
    const char* const* path,
    int npath,
    char buf[MAX_PATH_SIZE])
{
    int i;

    buf[0] = '\0';

    for (i = 0; i < npath; i++)
    {
        if (Strlcat(buf, path[i], MAX_PATH_SIZE) >= MAX_PATH_SIZE)
            return -1;

        if (i != 0 && i != npath - 1)
        {
            if (Strlcat(buf, "/", MAX_PATH_SIZE) >= MAX_PATH_SIZE)
                return -1;
        }
    }

    return 0;
}
Beispiel #15
0
static void
SelectUnicodeRange(AG_Event *event)
{
	char text[4][128];
	AG_Treetbl *tt = AG_PTR(1);
	AG_TlistItem *it = AG_PTR(2);
	struct unicode_range *range = it->p1;
	const struct unicode_range *next_range = NULL;
	Uint32 i, end;
	char *c;

	for (i = 0; i < unicodeRangeCount; i++) {
		if ((&unicodeRanges[i] == range) &&
		    (i+1 < unicodeRangeCount)) {
			next_range = &unicodeRanges[i+1];
			break;
		}
	}
	end = (next_range != NULL) ? next_range->start-1 : 0xffff;

	AG_TreetblClearRows(tt);
	
	for (i = range->start; i < end; i++) {
		if (i == 10)
			continue;
        
		/* prep column 0 */
		unitext[0] = i;
		AG_ExportUnicode(AG_UNICODE_TO_UTF8, utf8text, unitext,
		    sizeof(unitext));
		Snprintf(text[0], sizeof(text[0]), "%s", utf8text);
        
		/* prep column 1 */
		utf8seq[0] = '\0';
		for (c = &utf8text[0]; *c != '\0'; c++) {
			char s[4];
            
			Snprintf(s, sizeof(s), "%x", (unsigned char)*c);
			Strlcat(utf8seq, s, sizeof(utf8seq));
		}
		Snprintf(text[1], sizeof(text[1]), "%s", utf8seq);
        
		AG_TreetblAddRow(tt, NULL, i, "%s,%s", text[0], text[1]);
	}
}
Beispiel #16
0
void
rechist(void)
{
    Char    buf[BUFSIZ], hbuf[BUFSIZ], *hfile;
    int     fd, ftmp, oldidfds;
    struct  varent *shist;

    if (!fast) {
	/*
	 * If $savehist is just set, we use the value of $history
	 * else we use the value in $savehist
	 */
	if ((shist = adrof(STRsavehist)) != NULL) {
	    if (shist->vec[0][0] != '\0')
		(void) Strlcpy(hbuf, shist->vec[0], sizeof hbuf/sizeof(Char));
	    else if ((shist = adrof(STRhistory)) && shist->vec[0][0] != '\0')
		(void) Strlcpy(hbuf, shist->vec[0], sizeof hbuf/sizeof(Char));
	    else
		return;
	}
	else
	    return;

	if ((hfile = value(STRhistfile)) == STRNULL) {
	    Strlcpy(buf, value(STRhome), sizeof buf/sizeof(Char));
	    hfile = buf;
	    (void) Strlcat(buf, STRsldthist, sizeof buf/sizeof(Char));
	}

	if ((fd = open(short2str(hfile), O_WRONLY | O_CREAT | O_TRUNC,
	    0600)) == -1)
	    return;

	oldidfds = didfds;
	didfds = 0;
	ftmp = SHOUT;
	SHOUT = fd;
	dumphist[2] = hbuf;
	dohist(dumphist, NULL);
	SHOUT = ftmp;
	(void) close(fd);
	didfds = oldidfds;
    }
}
Beispiel #17
0
int MakeAbsolutePath(
    char buf[MAX_PATH_SIZE],
    const char* path)
{
    char cwd[MAX_PATH_SIZE];

    if (path[0] != '/')
    {
        if (getcwd(cwd, sizeof(cwd)) == (char*)0)
            return -1;

        if (Strlcpy2(buf, cwd, "/", MAX_PATH_SIZE) >= MAX_PATH_SIZE)
            return -1;
    }

    if (Strlcat(buf, path, MAX_PATH_SIZE) >= MAX_PATH_SIZE)
        return -1;

    return 0;
}
Beispiel #18
0
/* Initialize ProvReg strucutre from given directory */
_Use_decl_annotations_
MI_Result ProvReg_Init(ProvReg* self, const char* directory)
{
    RegFile* reg = NULL;
    Dir* dir = NULL;
    Dir* dir2 = NULL;
    MI_Result r = MI_RESULT_FAILED;
    
    /* Zero-fill self */
    memset(self, 0, sizeof(*self));

    dir = Dir_Open(directory);
    if (!dir)
    {
        return r;
    }

    /* Initialize batch allocator */
    Batch_Init(&self->batch, BATCH_MAX_PAGES);

    /* For each namespace directory in 'omirgister' */
    for (;;)
    {
        DirEnt* ent = Dir_Read(dir);

        if (!ent)
        {
            break;
        }

        /* Ignore system directories */
        if (strcmp(ent->name, ".") == 0 || strcmp(ent->name, "..") == 0)
            continue;

        /* Skip 'CVS' directories */
        if (strcmp(ent->name, "CVS") == 0)
            continue;

        /* Scan .reg files in the current namespace directory */
        {
            char path[PAL_MAX_PATH_SIZE];

            Strlcpy(path, directory, sizeof(path));
            Strlcat(path, "/", sizeof(path));
            Strlcat(path, ent->name, sizeof(path));

            /* Skip if not a dir */
            if(!Isdir(path))
                continue;

            dir2 = Dir_Open(path);
            if (!dir2)
            {
                goto failed;
            }

            for (;;)
            {
                DirEnt* ent2 = Dir_Read(dir2);
                if (!ent2)
                {
                    break;
                }

                /* Ignore system directories */
                if (strcmp(ent2->name,".") == 0 || strcmp(ent2->name,"..") == 0)
                {
                    continue;
                }

                /* Skip non-reg file */
                {
                    char* affix = Strrchr(ent2->name, '.');
                    if (!affix || (Strcasecmp(&affix[1], "reg") != 0))
                        continue;
                }

                /* Load the reg file */
                {
                    char regPath[PAL_MAX_PATH_SIZE];

                    /* Form path to .reg file */
                    Strlcpy(regPath, path, sizeof(regPath));
                    Strlcat(regPath, "/", sizeof(regPath));
                    Strlcat(regPath, ent2->name, sizeof(regPath));

                    /* Create new reg file object */
                    reg = RegFile_New(regPath);
                    if (!reg)
                    {
                        trace_ProvReg_SkipRegFile(scs(regPath));
                        continue;
                    }

                    /* For each class in the reg file */
                    {
                        RegClass* rc;
                        char* p = ent->name;
                        
                        /* Transpose NAMESPACE_SEPARATOR characters to '/' 
                         * characters 
                         */
                        while (*p)
                        {
                            if (*p == NAMESPACE_SEPARATOR)
                                *p = '/';
                            p++;
                        }

                        for (rc = reg->classesHead; rc; rc = rc->next)
                        {
                            if (_AddEntry(self, ent->name, reg, rc) != 0)
                            {
                                goto failed;
                            }
                        }
                    }

                    /* For each extraClass in the reg file */
                    {
                        RegClass* rc;
                        char* p = ent->name;
                        
                        /* Transpose NAMESPACE_SEPARATOR characters to '/' 
                         * characters 
                         */
                        while (*p)
                        {
                            if (*p == NAMESPACE_SEPARATOR)
                                *p = '/';
                            p++;
                        }

                        for (rc = reg->extraClassesHead; rc; rc = rc->next)
                        {
                            if (_AddEntryForExtraClass(self, ent->name, reg, rc) != 0)
                            {
                                goto failed;
                            }
                        }
                    }

                    /* Delete the current entry */
                    RegFile_Delete(reg);
                    reg = NULL;
                }
            }

            /* Close the directory */
            Dir_Close(dir2);
            dir2 = NULL;
        }
    }
    r = MI_RESULT_OK;

failed:
    if (dir2)
    {
        Dir_Close(dir2);
    }
    if (dir)
    {
        Dir_Close(dir);
    }
    if (r != MI_RESULT_OK)
    {
        ProvReg_Destroy(self);
        memset(self, 0, sizeof(*self));
    }
    if(reg)
    {
        RegFile_Delete(reg);
        reg = NULL;
    }
    return r;
}
Beispiel #19
0
static void
UpdateFaces(AG_Event *event)
{
	AG_Variable *bFont;
	AG_Font **pFont;
	AG_FontSelector *fs = AG_SELF();
	char fontPath[AG_SEARCHPATH_MAX], *pFontPath = &fontPath[0];
	AG_TlistItem *ti;
	char *s;
	int i;
	const int stdSizes[] = { 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
	                         22,24,26,28,32,48,64 };
	const int nStdSizes = sizeof(stdSizes) / sizeof(stdSizes[0]);
	
	bFont = AG_GetVariable(fs, "font", &pFont);
	AG_PushTextState();

	fs->flags &= ~(AG_FONTSELECTOR_UPDATE);

	for (i = 0; i < agBuiltinFontCount; i++) {
		AG_StaticFont *font = agBuiltinFonts[i];

		ti = AG_TlistAdd(fs->tlFaces, NULL, "_%s", font->name);
		ti->p1 = font;
		if (*pFont != NULL &&
		    strcmp(ti->text, OBJECT(*pFont)->name) == 0)
			ti->selected++;
	}

	AG_CopyCfgString("font-path", fontPath, sizeof(fontPath));
	while ((s = AG_Strsep(&pFontPath, ":")) != NULL) {
		AG_Dir *dir;
		int i;

		if ((dir = AG_OpenDir(s)) == NULL) {
			AG_Verbose(_("Ignoring: %s\n"), AG_GetError());
			continue;
		}
		for (i = 0; i < dir->nents; i++) {
			char path[AG_FILENAME_MAX];
			AG_FileInfo info;
			char *file = dir->ents[i], *pExt;

			if (file[0] == '.' ||
			    (pExt = strrchr(file, '.')) == NULL) {
				continue;
			}
			if (strcmp(pExt, ".ttf") != 0 &&
			    strcmp(pExt, ".TTF") != 0)
				continue;

			Strlcpy(path, s, sizeof(path));
			Strlcat(path, AG_PATHSEP, sizeof(path));
			Strlcat(path, file, sizeof(path));

			if (AG_GetFileInfo(path, &info) == -1 ||
			    info.type != AG_FILE_REGULAR) {
				continue;
			}
			ti = AG_TlistAddS(fs->tlFaces, NULL, file);
			if (*pFont != NULL &&
			    strcmp(file, OBJECT(*pFont)->name) == 0)
				ti->selected++;
		}
		AG_CloseDir(dir);
	}

	/* XXX */
	for (i = 0; i < nStdSizes; i++) {
		ti = AG_TlistAdd(fs->tlSizes, NULL, "%d", stdSizes[i]);
		if (*pFont != NULL &&
		    stdSizes[i] == (*pFont)->size)
			ti->selected++;
	}
	ti = AG_TlistAdd(fs->tlStyles, NULL, _("Regular"));
	if (*pFont != NULL && (*pFont)->flags == 0) { ti->selected++; }
	ti = AG_TlistAdd(fs->tlStyles, NULL, _("Italic"));
	if (*pFont != NULL && (*pFont)->flags == AG_FONT_ITALIC) { ti->selected++; }
	ti = AG_TlistAdd(fs->tlStyles, NULL, _("Bold"));
	if (*pFont != NULL && (*pFont)->flags == AG_FONT_BOLD) { ti->selected++; }
	ti = AG_TlistAdd(fs->tlStyles, NULL, _("Bold Italic"));
	if (*pFont != NULL && (*pFont)->flags == (AG_FONT_BOLD|AG_FONT_ITALIC)) { ti->selected++; }

	UpdatePreview(fs);

	AG_UnlockVariable(bFont);
}
Beispiel #20
0
AG_ProcessID
AG_Execute(const char *file, char **argv)
{
#ifdef _XBOX 
	AG_LAUNCH_DATA launchData = { LDT_TITLE };
	char xbePath[AG_PATHNAME_MAX];
	char xbeName[AG_FILENAME_MAX];
	char argstr[AG_ARG_MAX];
	char mntDev[AG_PATHNAME_MAX];
	char *p;
	DWORD xbeID;
	int i = 0;

	if(!file) {
		AG_SetError("No file provided for execution.");
		return (-1);
	}

	/* Get the destination xbe path */
	if(!argv || !argv[0] || (file && strcmp(file, argv[0]))) {
		p = (char *)file;
	} else {
		p = argv[0];
		i++;
	}

	/* Handle the command-line parameters */
	argstr[0] = '\0';
	if(argv) {
		while(argv[i] != NULL) {
			if( (AG_ARG_MAX - strlen(argstr) < strlen(argv[i]) + 1) ) {
				AG_SetError(_("%s: Supplied command arguments exceed AG_ARG_MAX (%d)"), 
					p, AG_ARG_MAX);
				return (-1);
			}
			Strlcat(argstr, argv[i], AG_ARG_MAX);
			Strlcat(argstr, " ", AG_ARG_MAX);
			i++;
		}
		Strlcpy(launchData.szCmdLine, argstr, AG_ARG_MAX);
	}

	/* Resolve the full xbe path */
	if((strlen(p) >= 7) && (!strncmp(p, "\\Device", 7))) {
		/* The xbe path was passed with the partition mapping */
		Strlcpy(xbePath, p, AG_PATHNAME_MAX);
	} else {
		char drive[3];
		char *dev;

		if(strlen(p) > 3 && isalpha(p[0]) && p[1] == ':' && p[2] == AG_PATHSEPCHAR) {
			/* The xbe path was passed with a drive letter */
			Strlcpy(drive, p, sizeof(drive));
			p = &p[3];
		} else {
			/* Path is relative */
			Strlcpy(drive, "D:", sizeof(drive));
		}
		if((dev = AG_XBOX_GetDeviceFromLogicalDrive(drive)) == NULL) {
			AG_SetError("Invalid or unsupported drive letter."
				" Please provide a valid drive letter or the full device path.");
			return (-1);
		}
		Strlcpy(xbePath, dev, sizeof(xbePath));
		if(xbePath[strlen(xbePath) - 1] != AG_PATHSEPCHAR && p[0] != AG_PATHSEPCHAR)
			Strlcat(xbePath, AG_PATHSEP, sizeof(xbePath));
		Strlcat(xbePath, p, sizeof(xbePath));
		Free(dev);
	}

	/* Isolate the xbe name */
	p = strrchr(xbePath, '\\') + 1;
	if(!p) {
		AG_SetError("No XBE Name included with path");
		return (-1);
	}
	Strlcpy(xbeName, p, AG_FILENAME_MAX);

	/* mntDev will be the D: path for the new xbe */
	Strlcpy(mntDev, xbePath, p - xbePath);
	mntDev[p - xbePath] = '\0';

	/* Get the xbe ID */
	if((xbeID = AG_XBOX_GetXbeTitleId(xbePath)) == -1) {
		AG_SetError("XBE is invalid or currupted");
		return (-1);
	}

	/* Complete the launch data */
	Strlcpy(launchData.szLauncherXBE, XeImageFileName->Buffer, XeImageFileName->Length + 1);
	Strlcpy(launchData.szLaunchedXBE, xbePath, sizeof(xbePath));

	/* Get the launcher ID */
	launchData.dwID = AG_XBOX_GetXbeTitleId(launchData.szLauncherXBE);

	launchData.magic = AG_LAUNCH_MAGIC;

	/* If this call succeeds the Agar application will be terminated so any
	   configs need to be saved prior to this call. */
	XWriteTitleInfoAndRebootA(xbeName, mntDev, LDT_TITLE, xbeID, &launchData);

	/* If we are here an error occurred */
	AG_SetError("XWriteTitleInfoAndRebootA failed.");
	return (-1);

#elif defined(_WIN32)
	STARTUPINFOA si;
	PROCESS_INFORMATION pi;
	char argstr[AG_ARG_MAX];
	int  i = 0;

	if(!file) {
		AG_SetError("No file provided for execution.");
		return (-1);
	}

	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi, sizeof(pi));

	if(file && strncmp(file, argv[0], strlen(file))) {
		strcpy(argstr, file);
		strcat(argstr, " ");
	} else {
		strcpy(argstr, argv[0]);
		strcat(argstr, " ");
		i++;
	}

	// Add the command-line parameters
	while(argv[i] != NULL) {
		if( (AG_ARG_MAX - strlen(argstr) < strlen(argv[i]) + 1) ) {
			AG_SetError(_("%s: Supplied command arguments exceed AG_ARG_MAX (%d)"), 
				file, AG_ARG_MAX);
			return (-1);
		}
		strcat(argstr, argv[i]);
		strcat(argstr, " ");
		i++;
	}

	if(CreateProcessA(NULL, argstr, NULL, NULL, FALSE, 
						0, NULL, NULL, &si, &pi) == 0) {
		AG_SetError(_("Failed to execute (%s)"), AG_Strerror(GetLastError()));
		return (-1);
	}
	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);

	return (pi.dwProcessId);

#elif defined(HAVE_EXECVP) && !defined(_WIN32)
	AG_ProcessID pid;

	if(!file) {
		AG_SetError("No file provided for execution.");
		return (-1);
	}

	if((pid = fork()) == -1) {
		AG_SetError(_("Fork failed (%s)"), AG_Strerror(errno));
		return (-1);
	} else if(pid == 0) {
		execvp(file, argv);

		// If we get here an error occurred
		_exit(EXIT_FAILURE);
	} else {
		return (pid);
	}

#endif
	AG_SetError("AG_Execute() is not supported on this platform");
	return (-1);
}
Beispiel #21
0
int PreExec_Exec(
    PreExec* self,
    const char* programPath,
    uid_t uid,
    uid_t gid)
{
    char path[PAL_MAX_PATH_SIZE];
    char key[PAL_MAX_PATH_SIZE];
    char uidBuf[11];
    const char* uidStr;
    char gidBuf[11];
    const char* gidStr;

    /* If no pre-exec program, nothing to do */
    if (programPath == NULL)
        return 0;

    /* Form the UID string */
    {
        size_t dummy;
        uidStr = Uint32ToStr(uidBuf, (PAL_Uint32)uid, &dummy);
    }

    /* Form the GID string */
    {
        size_t dummy;
        gidStr = Uint32ToStr(gidBuf, (PAL_Uint32)gid, &dummy);
    }

    /* Form a hash key from PREEXEC+UID+GID */
    {
        key[0] = '\0';
        Strlcat(key, programPath, PAL_MAX_PATH_SIZE);
        Strlcat(key, "+", PAL_MAX_PATH_SIZE);
        Strlcat(key, uidStr, PAL_MAX_PATH_SIZE);
        Strlcat(key, "+", PAL_MAX_PATH_SIZE);
        Strlcat(key, gidStr, PAL_MAX_PATH_SIZE);
    }

    /* If key already in cache, then return without doing anything */
    {
        static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;

        pthread_mutex_lock(&s_mutex);

        if (_Contains(&self->cache, key))
        {
            pthread_mutex_unlock(&s_mutex);
            return 0;
        }

        /* Add key to cache */
        _Insert(&self->cache, key);
        pthread_mutex_unlock(&s_mutex);
    }

    /* Form the full path of the pre-exec program */
    {
        const char* bindir = OMI_GetPath(ID_BINDIR);

        path[0] = '\0';

        if (bindir)
        {
            Strlcat(path, bindir, PAL_MAX_PATH_SIZE);
            Strlcat(path, "/", PAL_MAX_PATH_SIZE);
        }

        Strlcat(path, programPath, PAL_MAX_PATH_SIZE);
    }

    /* Execute and wait on the pre-exec program to exit */
    _BlockSIGCHLD();
    {
        pid_t pid = _Exec(path, uidStr, gidStr);

        if (pid == -1)
        {
            _UnblockSIGCHLD();
            trace_PreExecFailed(path);
            return -1;
        }

        {
            pid_t r;
            int status;

            r = waitpid(pid, &status, 0);

            if (r != pid || WEXITSTATUS(status) != 0)
            {
                _UnblockSIGCHLD();
                trace_PreExecFailed(path);
                return -1;
            }
        }
    }
    _UnblockSIGCHLD();

    trace_PreExecOk(path);
    return 0;
}
Beispiel #22
0
static void
setDolp(Char *cp)
{
    Char *dp;
    int i;

    if (dolnmod == 0 || dolmcnt == 0) {
	dolp = cp;
	return;
    }
    dp = cp = Strsave(cp);
    for (i = 0; i < dolnmod; i++) {
	/* handle s// [eichin:19910926.0510EST] */
	if(dolmod[i] == 's') {
	    int delim;
	    Char *lhsub, *rhsub, *np;
	    size_t lhlen = 0, rhlen = 0;
	    int didmod = 0;

	    delim = dolmod[++i];
	    if (!delim || letter(delim)
		|| Isdigit(delim) || any(" \t\n", delim)) {
		seterror(ERR_BADSUBST);
		break;
	    }
	    lhsub = &dolmod[++i];
	    while(dolmod[i] != delim && dolmod[++i]) {
		lhlen++;
	    }
	    dolmod[i] = 0;
	    rhsub = &dolmod[++i];
	    while(dolmod[i] != delim && dolmod[++i]) {
		rhlen++;
	    }
	    dolmod[i] = 0;

	    do {
		dp = Strstr(cp, lhsub);
		if (dp) {
		    size_t len = Strlen(cp) + 1 - lhlen + rhlen;

		    np = xreallocarray(NULL, len, sizeof(Char));
		    *dp = 0;
		    (void) Strlcpy(np, cp, len);
		    (void) Strlcat(np, rhsub, len);
		    (void) Strlcat(np, dp + lhlen, len);

		    xfree(cp);
		    dp = cp = np;
		    didmod = 1;
		} else {
		    /* should this do a seterror? */
		    break;
		}
	    }
	    while (dolwcnt == 10000);
	    /*
	     * restore dolmod for additional words
	     */
	    dolmod[i] = rhsub[-1] = delim;
	    if (didmod)
		dolmcnt--;
	    else
		break;
	} else {
	    int didmod = 0;

	    do {
		if ((dp = domod(cp, dolmod[i]))) {
		    didmod = 1;
		    if (Strcmp(cp, dp) == 0) {
			xfree(cp);
			cp = dp;
			break;
		    }
		    else {
			xfree(cp);
			cp = dp;
		    }
		}
		else
		    break;
	    }
	    while (dolwcnt == 10000);
	    dp = cp;
	    if (didmod)
		dolmcnt--;
	    else
		break;
	}
    }

    if (dp) {
	addla(dp);
	xfree(dp);
    }
    else
	addla(cp);

    dolp = STRNULL;
    if (seterr)
	stderror(ERR_OLD);
}
Beispiel #23
0
int main()
{
    /* DirName() */
    {
        PEGASUS_TEST_ASSERT(test("/aaa", "/") == 0);
        PEGASUS_TEST_ASSERT(test("/aaa/", "/") == 0);
        PEGASUS_TEST_ASSERT(test("/aaa/bbb", "/aaa") == 0);
        PEGASUS_TEST_ASSERT(test("/aaa/bbb/ccc", "/aaa/bbb") == 0);
        PEGASUS_TEST_ASSERT(test("aaa/bbb", "aaa") == 0);
        PEGASUS_TEST_ASSERT(test("aaa", ".") == 0);
        PEGASUS_TEST_ASSERT(test("aaa/", ".") == 0);
        PEGASUS_TEST_ASSERT(test("", ".") == 0);
        PEGASUS_TEST_ASSERT(test("/", "/") == 0);
        PEGASUS_TEST_ASSERT(test("////", "/") == 0);
        PEGASUS_TEST_ASSERT(test("/etc/passwd", "/etc") == 0);
    }

    /* GetHomedPath() */
    {
        char expect[EXECUTOR_BUFFER_SIZE];
        char actual[EXECUTOR_BUFFER_SIZE];
        const char* home;

        PEGASUS_TEST_ASSERT((home = getenv("PEGASUS_HOME")) != NULL);

        /* Test relative path */
        Strlcpy(expect, home, sizeof(expect));
        Strlcat(expect, "/somefile", sizeof(expect));

        PEGASUS_TEST_ASSERT(GetHomedPath("somefile", actual) == 0);
        PEGASUS_TEST_ASSERT(strcmp(expect, actual) == 0);

        /* Test absolute path */
        memset(actual, 0, sizeof(actual));
        PEGASUS_TEST_ASSERT(GetHomedPath(expect, actual) == 0);
        PEGASUS_TEST_ASSERT(strcmp(expect, actual) == 0);

        /* Test null path */
        memset(actual, 0, sizeof(actual));
        PEGASUS_TEST_ASSERT(GetHomedPath(NULL, actual) == 0);
        PEGASUS_TEST_ASSERT(strcmp(home, actual) == 0);
    }

    /* GetPegasusInternalBinDir() */
    {
        char expect[EXECUTOR_BUFFER_SIZE];
        char actual[EXECUTOR_BUFFER_SIZE];
        const char* home;

        PEGASUS_TEST_ASSERT((home = getenv("PEGASUS_HOME")) != NULL);
        Strlcpy(expect, home, sizeof(expect));
        Strlcat(expect, "/bin", sizeof(expect));

        PEGASUS_TEST_ASSERT(GetPegasusInternalBinDir(actual) == 0);
        PEGASUS_TEST_ASSERT(strcmp(expect, actual) == 0);
    }

    /* Remove PEGASUS_HOME from the environment */

    UnsetEnvironmentVariable("PEGASUS_HOME");

    /* GetHomedPath() with no PEGASUS_HOME defined */
    {
        char buffer[EXECUTOR_BUFFER_SIZE];
        PEGASUS_TEST_ASSERT(GetHomedPath("somefile", buffer) != 0);
    }

    /* GetPegasusInternalBinDir() with no PEGASUS_HOME defined */
    {
        char buffer[EXECUTOR_BUFFER_SIZE];
        PEGASUS_TEST_ASSERT(GetPegasusInternalBinDir(buffer) != 0);
    }

    printf("+++++ passed all tests\n");

    return 0;
}
Beispiel #24
0
/*
 * dcanon - canonicalize the pathname, removing excess ./ and ../ etc.
 *	we are of course assuming that the file system is standardly
 *	constructed (always have ..'s, directories have links)
 */
Char   *
dcanon(Char *cp, Char *p)
{
    Char *sp;
    Char *p1, *p2;	/* general purpose */
    bool    slash;

    Char    link[PATH_MAX];
    char    tlink[PATH_MAX];
    int     cc;
    Char   *newcp;

    /*
     * christos: if the path given does not start with a slash prepend cwd. If
     * cwd does not start with a path or the result would be too long abort().
     */
    if (*cp != '/') {
	Char    tmpdir[PATH_MAX];

	p1 = value(STRcwd);
	if (p1 == NULL || *p1 != '/')
	    abort();
	if (Strlen(p1) + Strlen(cp) + 1 >= PATH_MAX)
	    abort();
	(void) Strlcpy(tmpdir, p1, sizeof tmpdir/sizeof(Char));
	(void) Strlcat(tmpdir, STRslash, sizeof tmpdir/sizeof(Char));
	(void) Strlcat(tmpdir, cp, sizeof tmpdir/sizeof(Char));
	free(cp);
	cp = p = Strsave(tmpdir);
    }

    while (*p) {		/* for each component */
	sp = p;			/* save slash address */
	while (*++p == '/')	/* flush extra slashes */
	    continue;
	if (p != ++sp)
	    for (p1 = sp, p2 = p; (*p1++ = *p2++) != '\0';)
		continue;
	p = sp;			/* save start of component */
	slash = 0;
	while (*p)		/* find next slash or end of path */
	    if (*++p == '/') {
		slash = 1;
		*p = 0;
		break;
	    }

	if (*sp == '\0')	/* if component is null */
	    if (--sp == cp)	/* if path is one char (i.e. /) */
		break;
	    else
		*sp = '\0';
	else if (sp[0] == '.' && sp[1] == 0) {
	    if (slash) {
		for (p1 = sp, p2 = p + 1; (*p1++ = *p2++) != '\0';)
		    continue;
		p = --sp;
	    }
	    else if (--sp != cp)
		*sp = '\0';
	}
	else if (sp[0] == '.' && sp[1] == '.' && sp[2] == 0) {
	    /*
	     * We have something like "yyy/xxx/..", where "yyy" can be null or
	     * a path starting at /, and "xxx" is a single component. Before
	     * compressing "xxx/..", we want to expand "yyy/xxx", if it is a
	     * symbolic link.
	     */
	    *--sp = 0;		/* form the pathname for readlink */
	    if (sp != cp && !adrof(STRignore_symlinks) &&
		(cc = readlink(short2str(cp), tlink,
			       sizeof tlink-1)) >= 0) {
		tlink[cc] = '\0';
		(void) Strlcpy(link, str2short(tlink), sizeof link/sizeof(Char));

		if (slash)
		    *p = '/';
		/*
		 * Point p to the '/' in "/..", and restore the '/'.
		 */
		*(p = sp) = '/';
		/*
		 * find length of p
		 */
		for (p1 = p; *p1++;)
		    continue;
		if (*link != '/') {
		    /*
		     * Relative path, expand it between the "yyy/" and the
		     * "/..". First, back sp up to the character past "yyy/".
		     */
		    while (*--sp != '/')
			continue;
		    sp++;
		    *sp = 0;
		    /*
		     * New length is "yyy/" + link + "/.." and rest
		     */
		    p1 = newcp = xreallocarray(NULL,
			(sp - cp) + cc + (p1 - p), sizeof(Char));
		    /*
		     * Copy new path into newcp
		     */
		    for (p2 = cp; (*p1++ = *p2++) != '\0';)
			continue;
		    for (p1--, p2 = link; (*p1++ = *p2++) != '\0';)
			continue;
		    for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
			continue;
		    /*
		     * Restart canonicalization at expanded "/xxx".
		     */
		    p = sp - cp - 1 + newcp;
		}
		else {
		    /*
		     * New length is link + "/.." and rest
		     */
		    p1 = newcp = xreallocarray(NULL, cc + (p1 - p),
		        sizeof(Char));
		    /*
		     * Copy new path into newcp
		     */
		    for (p2 = link; (*p1++ = *p2++) != '\0';)
			continue;
		    for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
			continue;
		    /*
		     * Restart canonicalization at beginning
		     */
		    p = newcp;
		}
		free(cp);
		cp = newcp;
		continue;	/* canonicalize the link */
	    }
	    *sp = '/';
	    if (sp != cp)
		while (*--sp != '/')
		    continue;
	    if (slash) {
		for (p1 = sp + 1, p2 = p + 1; (*p1++ = *p2++) != '\0';)
		    continue;
		p = sp;
	    }
	    else if (cp == sp)
		*++sp = '\0';
	    else
		*sp = '\0';
	}
	else {			/* normal dir name (not . or .. or nothing) */

	    if (sp != cp && adrof(STRchase_symlinks) &&
		!adrof(STRignore_symlinks) &&
		(cc = readlink(short2str(cp), tlink,
			       sizeof tlink-1)) >= 0) {
		tlink[cc] = '\0';
		(void) Strlcpy(link, str2short(tlink), sizeof link/sizeof(Char));

		/*
		 * restore the '/'.
		 */
		if (slash)
		    *p = '/';

		/*
		 * point sp to p (rather than backing up).
		 */
		sp = p;

		/*
		 * find length of p
		 */
		for (p1 = p; *p1++;)
		    continue;
		if (*link != '/') {
		    /*
		     * Relative path, expand it between the "yyy/" and the
		     * remainder. First, back sp up to the character past
		     * "yyy/".
		     */
		    while (*--sp != '/')
			continue;
		    sp++;
		    *sp = 0;
		    /*
		     * New length is "yyy/" + link + "/.." and rest
		     */
		    p1 = newcp = xreallocarray(NULL,
			  (sp - cp) + cc + (p1 - p), sizeof(Char));
		    /*
		     * Copy new path into newcp
		     */
		    for (p2 = cp; (*p1++ = *p2++) != '\0';)
			continue;
		    for (p1--, p2 = link; (*p1++ = *p2++) != '\0';)
			continue;
		    for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
			continue;
		    /*
		     * Restart canonicalization at expanded "/xxx".
		     */
		    p = sp - cp - 1 + newcp;
		}
		else {
		    /*
		     * New length is link + the rest
		     */
		    p1 = newcp = xreallocarray(NULL, cc + (p1 - p), sizeof(Char));
		    /*
		     * Copy new path into newcp
		     */
		    for (p2 = link; (*p1++ = *p2++) != '\0';)
			continue;
		    for (p1--, p2 = p; (*p1++ = *p2++) != '\0';)
			continue;
		    /*
		     * Restart canonicalization at beginning
		     */
		    p = newcp;
		}
		free(cp);
		cp = newcp;
		continue;	/* canonicalize the link */
	    }
	    if (slash)
		*p = '/';
	}
    }

    /*
     * fix home...
     */
    p1 = value(STRhome);
    cc = Strlen(p1);
    /*
     * See if we're not in a subdir of STRhome
     */
    if (p1 && *p1 == '/' &&
	(Strncmp(p1, cp, cc) != 0 || (cp[cc] != '/' && cp[cc] != '\0'))) {
	static ino_t home_ino = -1;
	static dev_t home_dev = -1;
	static Char *home_ptr = NULL;
	struct stat statbuf;

	/*
	 * Get dev and ino of STRhome
	 */
	if (home_ptr != p1 &&
	    stat(short2str(p1), &statbuf) != -1) {
	    home_dev = statbuf.st_dev;
	    home_ino = statbuf.st_ino;
	    home_ptr = p1;
	}
	/*
	 * Start comparing dev & ino backwards
	 */
	Strlcpy(link, cp, sizeof link/sizeof(Char));
	p2 = link;
	for (sp = NULL; *p2 && stat(short2str(p2), &statbuf) != -1;) {
	    if (statbuf.st_dev == home_dev &&
		statbuf.st_ino == home_ino) {
		sp = (Char *) - 1;
		break;
	    }
	    if ((sp = Strrchr(p2, '/')) != NULL)
		*sp = '\0';
	}
	/*
	 * See if we found it
	 */
	if (*p2 && sp == (Char *) -1) {
	    /*
	     * Use STRhome to make '~' work
	     */
	    newcp = Strspl(p1, cp + Strlen(p2));
	    free(cp);
	    cp = newcp;
	}
    }
    return cp;
}