e16-menuedit/src/file.c

529 lines
12 KiB
C

/* Copyright (C) 2004 Andreas Volz and various contributors
*
* Permission is hereby granted, free of charge, to any person ob-
* taining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restric-
* tion, including without limitation the rights to use, copy, modi-
* fy, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is fur-
* nished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies of the Software, its documentation and
* marketing & publicity materials, and acknowledgment shall be giv-
* en in the documentation, materials and software packages that
* this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONIN-
* FRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CON-
* TRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* File: file.c
* Created by: Andreas Volz <linux@brachttal.net>
*
*/
#include "file.h"
extern struct global_variables gv;
char *homedir (int uid)
{
char *s;
static int usr_uid = -1;
static char *usr_s = NULL;
struct passwd *pwd;
if (usr_uid < 0)
usr_uid = getuid ();
if ((uid == usr_uid) && (usr_s))
{
return (g_strdup (usr_s));
}
pwd = getpwuid (uid);
if (pwd)
{
s = g_strdup (pwd->pw_dir);
if (uid == usr_uid)
usr_s = g_strdup (s);
return (s);
}
return (g_strdup
((!getenv("TMPDIR")) ? "/tmp" : getenv ("TMPDIR")));
}
void compile_regex ()
{
int status;
char err_buf[ERR_BUF_SIZE];
char pattern_mark[] = "\"([^\"]*)\"[[:space:]]*";
char pattern_char[] = "([^[[:space:]]*)[[:space:]]*";
char pattern_space[] = "[[:space:]]*(.*)";
status = regcomp (&gv.re_mark, pattern_mark, REG_EXTENDED);
if (status != 0)
{
regerror (status, &gv.re_mark, err_buf, (size_t) ERR_BUF_SIZE);
printf ("regex compile: %s\n", err_buf);
}
status = regcomp (&gv.re_char, pattern_char, REG_EXTENDED);
if (status != 0)
{
regerror (status, &gv.re_mark, err_buf, (size_t) ERR_BUF_SIZE);
printf ("regex compile: %s\n", err_buf);
}
status = regcomp (&gv.re_space, pattern_space, REG_EXTENDED);
if (status != 0)
{
regerror (status, &gv.re_mark, err_buf, (size_t) ERR_BUF_SIZE);
printf ("regex compile: %s\n", err_buf);
}
gv.pattern_mark = strdup (pattern_mark);
gv.pattern_char = strdup (pattern_char);
gv.pattern_space = strdup (pattern_space);
}
int menu_regex (char *line, gchar ***data_ptr)
{
struct substrings *ss = NULL;
int numsub = 0;
int maxsub = 1;
int status;
char err_buf[ERR_BUF_SIZE];
char **data;
int i, n;
data = malloc (4 * sizeof (*data));
*data_ptr = data;
line = strdup (line);
/* cut spaces */
if (line[0] == ' ')
{
status = regex_sub2 (&gv.re_space, line, gv.pattern_space,
&ss, maxsub, &numsub);
if (numsub >= 1)
{
free (line);
line = strdup (ss[1].match);
}
for (i = 0; i < numsub; i++)
{
free (ss[i].match);
free (ss[i].start);
free (ss[i].end);
}
free (ss);
}
/* parse data array */
for (n = 0; n < 4; n++)
{
data[n] = strdup ("");
if (line[0] == '\"')
{
status = regex_sub2 (&gv.re_mark, line, gv.pattern_mark,
&ss, maxsub, &numsub);
if (status != 0)
{
regerror (status, &gv.re_mark, err_buf, (size_t) ERR_BUF_SIZE);
printf ("regex exec: %s\n", err_buf);
}
if (numsub >= 1)
{
free (line);
line = strdup (ss[0].end);
free (data[n]);
data[n] = to_utf8 (ss[1].match);
}
for (i = 0; i < numsub; i++)
{
free (ss[i].match);
free (ss[i].start);
free (ss[i].end);
}
free (ss);
}
else if (line[0] != ' ')
{
status = regex_sub2 (&gv.re_char, line, gv.pattern_char,
&ss, maxsub, &numsub);
if (status != 0)
{
regerror (status, &gv.re_char, err_buf, (size_t) ERR_BUF_SIZE);
printf ("regex exec: %s\n", err_buf);
}
if (numsub >= 1)
{
free (line);
line = strdup (ss[0].end);
free (data[n]);
data[n] = to_utf8 (ss[1].match);
}
for (i = 0; i < numsub; i++)
{
free (ss[i].match);
free (ss[i].start);
free (ss[i].end);
}
free (ss);
}
}
return 0;
}
int mkdir_with_parent (const char *pathname, mode_t mode)
{
int err;
int i;
char *left;
char *tok;
char *pathname_copy = strdup (pathname);
i = 0;
do
{
tok = strtok_left (pathname_copy, "/", i);
if (!tok)
break;
left = strsplit (pathname_copy, NULL,
strlen (pathname_copy) - strlen (tok));
err = mkdir (left, mode);
i++;
}
while (tok);
free (pathname_copy);
return err;
}
char *strsplit (char *s, char **right, int count)
{
char *s_org = strdup (s);
if (count < strlen (s))
{
if (right)
strcpy (*right, s + count);
s_org[count]='\0';
}
return s_org;
}
char *strtok_left (char *s, const char *delim, unsigned int number)
{
int i;
char *pos = s;
char *s_new;
if (number == 0)
return s;
if (strcmp (s + strlen (s) - strlen (delim), delim))
{
s_new = malloc (strlen (s) + strlen (delim) + 1);
strcpy (s_new, s);
strcat (s_new, delim);
}
else
{
s_new = s;
}
for (i = 0; pos; i++)
{
pos = strstr (s_new, delim);
if (pos)
{
s_new = pos + (1 * strlen (delim));
if (i == number - 1)
{
pos = '\0';
return s_new;
}
}
}
return NULL;
}
/* if ver1 < ver2 -> return -1
* if ver1 > ver2 -> return 1
* if ver1 == ver2 -> return 0
*/
int version_cmp (char *ver1, char *ver2)
{
char *ver1_token;
char *ver2_token;
char *ver1_ptr = malloc (strlen (ver1)+1);
char *ver2_ptr = malloc (strlen (ver2)+1);
ver1_token = strtok_r (ver1, ".", &ver1_ptr);
ver2_token = strtok_r (ver2, ".", &ver2_ptr);
while ((ver1_token) || (ver2_token))
{
int ver1_i;
int ver2_i;
if (!ver1_token)
ver1_i = 0;
else
ver1_i = atoi (ver1_token);
if (!ver2_token)
ver2_i = 0;
else
ver2_i = atoi (ver2_token);
if (ver1_i < ver2_i)
return -1;
else if (ver1_i > ver2_i)
return 1;
ver1_token = strtok_r (NULL, ".", &ver1_ptr);
ver2_token = strtok_r (NULL, ".", &ver2_ptr);
}
return 0;
}
/* returns a version number of a pkg-config package
* the return char* could be freed after use
*/
char *pkg_config_version (char *package)
{
gboolean spawn;
const int buf_len = 128;
gchar buf[buf_len];
gchar *argv_child[4];
gint stdout_child;
gint stderr_child;
int ret_val;
argv_child[0] = g_strdup ("pkg-config");
argv_child[1] = g_strdup ("--modversion");
argv_child[2] = package;
argv_child[3] = NULL;
spawn = g_spawn_async_with_pipes (NULL, argv_child, NULL,
G_SPAWN_SEARCH_PATH, NULL,
NULL, NULL, NULL,
&stdout_child, &stderr_child, NULL);
g_free (argv_child[0]);
g_free (argv_child[1]);
ret_val = read (stdout_child, buf, buf_len);
if (ret_val == 0)
return 0;
else
return strdup (buf);
}
/* returns a version number of a pkg-config package
* the return char* could be freed after use
*/
char *e16_version ()
{
gboolean spawn;
const int buf_len = 1024;
gchar buf[buf_len];
gchar *argv_child[4];
gint stdout_child;
gint stderr_child;
int ret_val;
gchar buf2[buf_len];
argv_child[0] = g_strdup ("eesh");
argv_child[1] = g_strdup ("-ewait");
argv_child[2] = g_strdup ("ver");;
argv_child[3] = NULL;
spawn = g_spawn_async_with_pipes (NULL, argv_child, NULL,
G_SPAWN_SEARCH_PATH, NULL,
NULL, NULL, NULL,
&stdout_child, &stderr_child, NULL);
g_free (argv_child[0]);
g_free (argv_child[1]);
ret_val = read (stdout_child, buf, buf_len);
sscanf (buf, "Enlightenment-Version: enlightenment-%s\n", buf2);
if (ret_val == 0)
return 0;
else
return strdup (buf2);
}
char *get_fallback_locale (char *locale)
{
char *locale_dup;
char *pos = NULL;
locale_dup = strdup (locale);
pos = strrchr (locale_dup, '@');
if (pos)
{
strcpy (pos, "\0");
}
else
{
pos = strrchr (locale_dup, '_');
if (pos)
{
strcpy (pos, "\0");
}
else
{
pos = locale_dup;
strcpy (pos, "C");
}
}
return locale_dup;
}
int run_help (char *help_app, char *help_dir, char *help_file)
{
gboolean spawn;
gchar *argv_child[3];
gchar *params;
char *locale = NULL;
gboolean locale_failed = FALSE;
char *locale_fallback = NULL;
char *locale_tmp;
gboolean help_missing = TRUE;
struct stat buf;
/* Is there a better way to get the users current language? */
locale = setlocale (LC_MESSAGES, NULL);
/* If no locale is available use 'C' and free it later */
if (!locale)
{
locale_failed = TRUE;
locale = g_strdup_printf ("C");
}
params = g_strdup_printf ("%s/%s/%s", help_dir,
locale, help_file);
#ifdef DEBUG
DEBUG_OUTPUT printf ("%s\n", params);
#endif /* DEBUG */
help_missing = stat (params, &buf);
/* locale fallback 1 */
if (help_missing)
{
locale_fallback = get_fallback_locale (locale);
g_free (params);
params = g_strdup_printf ("%s/%s/%s", help_dir,
locale_fallback, help_file);
#ifdef DEBUG
DEBUG_OUTPUT printf ("Try help fallback1: %s\n", params);
#endif /* DEBUG */
help_missing = stat (params, &buf);
/* locale fallback 2 */
if (help_missing)
{
locale_tmp = strdup (locale_fallback);
g_free (locale_fallback);
locale_fallback = get_fallback_locale (locale_tmp);
g_free (locale_tmp);
g_free (params);
params = g_strdup_printf ("%s/%s/%s", help_dir,
locale_fallback, help_file);
#ifdef DEBUG
DEBUG_OUTPUT printf ("Try help fallback2: %s\n", params);
#endif /* DEBUG */
help_missing = stat (params, &buf);
/* locale fallback 3 */
if (help_missing)
{
locale_tmp = strdup (locale_fallback);
g_free (locale_fallback);
locale_fallback = get_fallback_locale (locale_tmp);
g_free (locale_tmp);
g_free (params);
params = g_strdup_printf ("%s/%s/%s", help_dir,
locale_fallback, help_file);
g_free (locale_fallback);
#ifdef DEBUG
DEBUG_OUTPUT printf ("Try help fallback4: %s\n", params);
#endif /* DEBUG */
help_missing = stat (params, &buf);
}
else
{
g_free (locale_fallback);
}
}
}
if (help_missing)
{
/* no help files found */
return 1;
}
else
{
argv_child[0] = help_app;
argv_child[1] = params;
argv_child[2] = NULL;
#ifdef DEBUG
DEBUG_OUTPUT printf ("Try exec help: %s %s\n", help_app, params);
#endif /* DEBUG */
spawn = g_spawn_async (NULL, argv_child, NULL,
G_SPAWN_SEARCH_PATH, NULL,
NULL, NULL, NULL);
if (!spawn)
{
/* no help application found */
return 2;
}
g_free (params);
}
if (locale_failed)
g_free (locale);
return 0;
}