/* win32lib.c: bits and pieces for win32 and msvc.
Copyright 2006, 2011-2013 Akira Kakuto.
Copyright 1996, 1997, 1998, 1999 Fabrice Popineau.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, see . */
#include
#include
#include
#include
static int is_include_space(const char *s)
{
char *p;
p = strchr(s, ' ');
if(p) return 1;
p = strchr(s, '\t');
if(p) return 1;
return 0;
}
FILE * win32_popen (const char *cmd, const char *fmode)
{
char mode[3];
char *p, *q;
const char *cmd2;
FILE *ret;
mode[0] = fmode[0];
mode[1] = 'b';
mode[2] = '\0';
if (is_include_space (cmd)) {
cmd2 = xmalloc (strlen (cmd) + 3);
q = (char *)cmd2;
p = (char *)cmd;
*q++= '\"';
while(*p)
*q++ = *p++;
*q++ = '\"';
*q = '\0';
ret = _popen (cmd2, mode);
free ((char *)cmd2);
return ret;
} else {
return _popen (cmd, mode);
}
}
int win32_pclose (FILE *f)
{
return _pclose (f);
}
/* large file support */
__int64
xftell64 (FILE *f, const char *filename)
{
#if _MSC_VER > 1200
__int64 where;
where = _ftelli64(f);
if (where < (__int64)0)
FATAL_PERROR(filename);
#else
__int64 where, filepos;
int fd;
fd = fileno(f);
if(f->_cnt < 0)
f->_cnt = 0;
if((filepos = _lseeki64(fd, (__int64)0, SEEK_CUR)) < (__int64)0) {
FATAL_PERROR(filename);
return (__int64)(-1);
}
if(filepos == (__int64)0)
where = (__int64)(f->_ptr - f->_base);
else
where = filepos - f->_cnt;
#endif
return where;
}
void
xfseek64 (FILE *f, __int64 offset, int wherefrom, const char *filename)
{
#if _MSC_VER > 1200
if (_fseeki64(f, offset, wherefrom) < (__int64)0)
FATAL_PERROR(filename);
#else
if(wherefrom == SEEK_CUR) {
offset += xftell64(f, filename);
wherefrom = SEEK_SET;
}
fflush(f);
if (_lseeki64(fileno(f), offset, wherefrom) < (__int64)0)
FATAL_PERROR(filename);
#endif
}
/* special TeXLive Ghostscript */
static int is_dir (char *buff)
{
struct stat stats;
return stat (buff, &stats) == 0 && S_ISDIR (stats.st_mode);
}
/*
TeXlive uses its own gs in
$SELFAUTOPARENT/tlpkg/tlgs
*/
void texlive_gs_init(void)
{
char *nptr, *path;
char tlgsbindir[512];
char tlgslibdir[512];
nptr = kpse_var_value("TEXLIVE_WINDOWS_EXTERNAL_GS");
if (nptr == NULL || !strcmp(nptr, "0") || !strcmp(nptr, "n") || !strcmp(nptr, "f")) {
if (nptr)
free (nptr);
nptr = kpse_var_value("SELFAUTOPARENT");
if (nptr) {
strcpy(tlgsbindir, nptr);
strcat(tlgsbindir,"/tlpkg/tlgs");
if(is_dir(tlgsbindir)) {
strcpy(tlgslibdir, tlgsbindir);
strcat(tlgslibdir, "/lib;");
strcat(tlgslibdir, tlgsbindir);
strcat(tlgslibdir, "/fonts");
strcat(tlgsbindir, "/bin;");
free(nptr);
for(nptr = tlgsbindir; *nptr; nptr++) {
if(*nptr == '/') *nptr = '\\';
}
nptr = getenv("PATH");
path = (char *)malloc(strlen(nptr) + strlen(tlgsbindir) + 6);
strcpy(path, tlgsbindir);
strcat(path, nptr);
xputenv("PATH", path);
xputenv("GS_LIB", tlgslibdir);
}
}
} else {
free (nptr);
}
}
/*
path name in char *input is changed into the long
name format and returned in char *buff.
return value: 0 if failed
1 if succeeded
*/
int getlongpath(char *buff, char *input, int len)
{
HANDLE hnd;
WIN32_FIND_DATA ffd;
int cnt = 0;
char *p, *q, *r;
buff[0] = '\0';
/*
temporarily change directory separators into back slashs
*/
for(p = input; *p; p++) {
if(*p == '/')
*p = '\\';
}
p = q = input;
r = buff;
/*
UNC name
*/
if(q[0] == '\\' && q[1] == '\\') {
cnt += 2;
if(cnt > len) return 0;
buff[0] = '/';
buff[1] = '/';
p += 2;
r += 2;
while(*p != '\\' && *p) {
if (IS_KANJI(p)) {
cnt++;
if(cnt > len) return 0;
*r++ = *p++;
}
cnt++;
if(cnt > len) return 0;
*r++ = *p++;
}
cnt++;
if(cnt > len) return 0;
*r++ = '/';
if(*p) p++;
while(*p != '\\' && *p) {
if (IS_KANJI(p)) {
cnt++;
if(cnt > len) return 0;
*r++ = *p++;
}
cnt++;
if(cnt > len) return 0;
*r++ = *p++;
}
cnt++;
if(cnt > len) return 0;
*r++ = '/';
*r= '\0';
if(*p) p++;
/*
drive name
*/
} else if(isalpha(q[0]) && q[1] == ':' && q[2] == '\\') {
*r++ = q[0];
*r++ = ':';
*r++ = '/';
*r = '\0';
p += 3;
cnt += 3;
if(cnt > len) return 0;
}
for( ; *p; p++) {
if(IS_KANJI(p)) {
p++;
continue;
}
if(*p == '\\') {
*p = '\0';
if((hnd = FindFirstFile(q, &ffd)) == INVALID_HANDLE_VALUE) {
return 0;
}
FindClose(hnd);
cnt += strlen(ffd.cFileName);
cnt++;
if(cnt > len) return 0;
strcat(buff, ffd.cFileName);
strcat(buff, "/");
*p = '\\';
}
}
/*
file itself
*/
if((hnd = FindFirstFile(q, &ffd)) == INVALID_HANDLE_VALUE) {
return 0;
}
FindClose(hnd);
cnt += strlen(ffd.cFileName);
if(cnt > len) return 0;
strcat(buff, ffd.cFileName);
return 1;
}
/* user info */
/* Adapted for XEmacs by David Hobley */
/* Sync'ed with Emacs 19.34.6 by Marc Paquette */
/* Adapted to fpTeX 0.4 by Fabrice Popineau */
char * get_home_directory()
{
char *p;
char *home = getenv("HOME");
if(!home)
home = getenv("USERPROFILE");
if(home) {
home = xstrdup(home);
for(p = home; *p; p++) {
if(IS_KANJI(p)) {
p++;
continue;
}
if(*p == '\\')
*p = '/';
}
}
return home;
}
int
kpathsea_getuid (kpathsea kpse)
{
return kpse->the_passwd.pw_uid;
}
int
kpathsea_getgid (kpathsea kpse)
{
return kpse->the_passwd.pw_gid;
}
struct passwd *
kpathsea_getpwuid (kpathsea kpse, int uid)
{
if (uid == kpse->the_passwd.pw_uid)
return &kpse->the_passwd;
return NULL;
}
struct passwd *
kpathsea_getpwnam (kpathsea kpse, char *name)
{
struct passwd *pw;
pw = kpathsea_getpwuid (kpse, kpathsea_getuid (kpse));
if (!pw)
return pw;
if (stricmp (name, pw->pw_name))
return NULL;
return pw;
}
void
kpathsea_init_user_info (kpathsea kpse)
{
char *home;
DWORD nSize = 256;
if (!GetUserName (kpse->the_passwd.pw_name, &nSize))
strcpy (kpse->the_passwd.pw_name, "unknown");
kpse->the_passwd.pw_uid = 123;
kpse->the_passwd.pw_gid = 123;
/* Ensure HOME and SHELL are defined. */
home = get_home_directory();
if (home) {
putenv(concat("HOME=", home));
}
else {
putenv ("HOME=c:/");
}
if (getenv ("SHELL") == NULL)
putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
{
/* If TEXMFTEMP is defined, then use it as the TEMP and TMP variables. */
char *p;
if ((p = getenv("TEXMFTEMP")) != NULL) {
putenv(concat("TEMP=", p));
putenv(concat("TMP=", p));
}
}
/* Set dir and shell from environment variables. */
strcpy (kpse->the_passwd.pw_dir, get_home_directory());
strcpy (kpse->the_passwd.pw_shell, getenv ("SHELL"));
}
/* win32_system */
int win32_system(const char *cmd)
{
const char *p;
char *q;
char *av[4];
int len, ret;
int spacep = 0;
if(cmd == NULL)
return 1;
av[0] = xstrdup("cmd.exe");
av[1] = xstrdup("/c");
len = strlen(cmd) + 3;
spacep = is_include_space(cmd);
av[2] = malloc(len);
q = av[2];
if(spacep)
*q++ = '"';
for(p = cmd; *p; p++, q++) {
if(*p == '\'')
*q = '"';
else
*q = *p;
}
if(spacep)
*q++ = '"';
*q = '\0';
av[3] = NULL;
ret = spawnvp(_P_WAIT, av[0], av);
free(av[0]);
free(av[1]);
free(av[2]);
return ret;
}
#if defined (KPSE_COMPAT_API)
int
getuid (void)
{
return kpathsea_getuid(kpse_def);
}
int
geteuid (void)
{
/* I could imagine arguing for checking to see whether the user is
in the Administrators group and returning a UID of 0 for that
case, but I don't know how wise that would be in the long run. */
return getuid ();
}
int
getgid (void)
{
return kpathsea_getgid (kpse_def);
}
int
getegid (void)
{
return getgid ();
}
struct passwd *
getpwuid (int uid)
{
return kpathsea_getpwuid (kpse_def, uid);
}
struct passwd *
getpwnam (char *name)
{
return kpathsea_getpwnam (kpse_def, name);
}
#endif /* KPSE_COMPAT_API */