linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* segfault with strdup
@ 2003-05-20 11:20 Martin Buchan
  2003-05-20 12:25 ` Chris Nanakos
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Martin Buchan @ 2003-05-20 11:20 UTC (permalink / raw)
  To: linux-c-programming

Hi,

I have built a C program which parses an XML file containing
application names and the command to run those applications. Once i
parse the file, i then build a GTK menu - like the GNOME start
button thingy with all the apps put into their relevant sections. I.e.

Internet    -> Web Browsers -> Mozilla Web Browser
                            -> Netscape Navigator 
                            -> Lynx Text Only Browser

            -> Email        -> Mozilla Mail
                            -> Mutt
		  
Programming -> Anjuta
            -> Sun Forte



Etc etc.

How i build the menu is by parsing the XML file and sticking the
results in an array of structs and then looping thru the array and
building the buttons, submenu and menu entries.

This is all working now, however, it only works if i run it in the
directory that i have done all my coding in. I.e. If i compile and
install to a different location, i get a seg fault when parsing the
XML file. Its not that it cant find the file, it goes thru and
parses the first entry in the file and then croaks on the 2nd
while parsing the name of the app - which is "Netscape Navigator"
If i shorten the name to just "Netscape", it then croaks on the 3rd
entry which is "Lynx Text Only Browser", if i then shorten this to
just "Lynx Browser", it then croaks on the 4th and so on and so on.

I have some #define 's which state the location of some of my files
like so:

#define APPLIST "/home/bm98/prg/gtk-menu/current/applist.xml"
#define XPMDIR "/home/bm98/prg/gtk-menu/current/xpms/"
#define HELPDIR "/home/bm98/prg/gtk-menu/current/help/"

If i use these locations, it works fine but if i change it to 

#define APPLIST "/home/bm98/menu/applist.xml"
#define XPMDIR "/home/bm98/menu/xpms/"
#define HELPDIR "/home/bm98/menu/help/"

It doesnt work. (Ultimately i want to get these values from a
./configure script with a --prefix=XXX so that i dont need to 
hard code it etc)

Here is my struct

struct menuentry
{
  gchar *appsection;
  gchar *sectionxpm;
  gchar *appsubmenu;
  gchar *appname;
  gchar *appcommand;
};
			 
typedef struct menuentry menuentry;
			 
And here is how i allocate space for it.

menuentry *mePtr = malloc( n * sizeof (menuentry) );


As i say, this works fine for the first set of locations, but not
for the second.

The place where it is seg faulting is

uri = xmlGetProp(cur, "name");
mePtr[i].appname = strdup(uri);  /* HERE */

Here is some output from DDD:

#3  0x123fc in parseApp (doc=0x3d450, cur=0x39c98, mePtr=0x29708, i=1) at menu-0.9.1.c:207
#2  0xfeccf2a4 in strdup () from /usr/lib/libc.so.1
#1  0xfecc1c90 in malloc () from /usr/lib/libc.so.1
#0  0xfecc1c48 in _smalloc () from /usr/lib/libc.so.1


Can anyone spot anything from this info where I am going wrong. I
will gladly post more info from ddd or more of my source code if
this will help.


Thanks
Martin

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: segfault with strdup
  2003-05-20 11:20 segfault with strdup Martin Buchan
@ 2003-05-20 12:25 ` Chris Nanakos
  2003-05-20 12:46   ` Martin Buchan
  2003-05-20 13:12   ` Martin Buchan
       [not found] ` <200305201316.h4KDGUhG007842@grinch.txt.com>
  2003-05-20 16:32 ` Glynn Clements
  2 siblings, 2 replies; 7+ messages in thread
From: Chris Nanakos @ 2003-05-20 12:25 UTC (permalink / raw)
  To: Martin Buchan, linux-c-programming

Can you send the source code???



 To unsubscribe from this list: send the line "unsubscribe
linux-c-programming" in
 the body of a message to majordomo@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: segfault with strdup
  2003-05-20 12:25 ` Chris Nanakos
@ 2003-05-20 12:46   ` Martin Buchan
  2003-05-20 13:12   ` Martin Buchan
  1 sibling, 0 replies; 7+ messages in thread
From: Martin Buchan @ 2003-05-20 12:46 UTC (permalink / raw)
  To: linux-c-programming; +Cc: Chris Nanakos

[-- Attachment #1: Type: text/plain, Size: 499 bytes --]

On Tue, May 20, 2003 at 03:25:31PM +0300, Chris Nanakos wrote:
> Can you send the source code???

Here is the code. All 869 lines of it. :-)                        
I would have snipped it and included only the relevant sections but 
i am totally at a loss as to why this is happening and hence dont     
know what the relevant sections are. Also included is the menu.h    
file which contains the #define 's and some XPM data.

Thanks again. 
                                   
Martin          



[-- Attachment #2: menu-0.9.1.c --]
[-- Type: text/plain, Size: 24498 bytes --]

/* CMS Gtk+ Menu for newbians
 * Version 0.7 MJB - 2003 
 * gcc -Wall menu-0.9.1.c -o menu-0.9.1 `gtk-config --cflags` `gtk-config --libs` \
 * -I/usr/local/include/libxml2 -Wall -lxml2 -Wno-parentheses
 */
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/tree.h>
#include "menu.h"

static gint button_press (GtkWidget *, GdkEvent *);
extern int xmlDoValidityCheckingDefaultValue;

struct termentry 
{
  gchar *termxpm;
  gchar *termname;
  gchar *termcmd;
};

typedef struct termentry termentry;

struct menuentry 
{
  gchar *appsection;
  gchar *sectionxpm;
  gchar *appsubmenu;
  gchar *appname;
  gchar *appcommand;
};

typedef struct menuentry menuentry;

/* Count how many apps we have in applist.xml */
float countElements(char *docname) 
{
  xmlDocPtr doc;
  xmlXPathContextPtr ctx;
  xmlXPathObjectPtr path;
  float i = 0.0;
  
  xmlKeepBlanksDefault(1);
  doc = xmlParseFile(docname);
  
  xmlXPathInit();
  ctx = xmlXPathNewContext(doc);
  
  path = xmlXPathEvalExpression((const xmlChar *)"count(/*/section)", ctx);
  i = path->floatval;
  
  xmlXPathFreeObject(path);
  xmlXPathFreeContext(ctx);
  xmlFreeDoc(doc);
  return i;
}

/* Count how many submenus we have in applist.xml */
float countSubmenus(char *docname) 
{
  xmlDocPtr doc;
  xmlXPathContextPtr ctx;
  xmlXPathObjectPtr path;
  float i = 0.0;
  
  xmlKeepBlanksDefault(1);
  doc = xmlParseFile(docname);
  
  xmlXPathInit();
  ctx = xmlXPathNewContext(doc);
  
  path = xmlXPathEvalExpression((const xmlChar *)"count(/*/section/submenu)", ctx);
  i = path->floatval;
  
  xmlXPathFreeObject(path);
  xmlXPathFreeContext(ctx);
  xmlFreeDoc(doc);
  return i;
}

int countSections(char *docname) 
{
  xmlDocPtr doc;
  xmlNodePtr cur;
  xmlChar *uri;
  xmlChar *tmp = "null";
  int n = 0;
							
  doc = xmlParseFile(docname);
  cur = xmlDocGetRootElement(doc);
  
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"root")))
		  {
			 cur = cur->xmlChildrenNode;
			 while (cur != NULL) 
				{
				  if ((!xmlStrcmp(cur->name, (const xmlChar *)"section")))
					 {
						uri = xmlGetProp(cur, "name");
						if ((strcmp(uri, tmp) != 0 )) 
						  n++;
						tmp = uri;
					 }
				  cur = cur->next;
				}
		  }
	 }
  return n;
}

/* Parse command line arguments of New Terminal */
void parseTermCommand (xmlDocPtr doc, xmlNodePtr cur, termentry *termPtr)
{
  xmlChar *key;
  cur = cur->xmlChildrenNode;
  
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"termcmd")))
		  {
			 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
			 termPtr[0].termcmd = strdup(key);
			 xmlFree(key);
		  }
		cur = cur->next;
	 }
}

void parseTermXpm (xmlDocPtr doc, xmlNodePtr cur, termentry *termPtr)
{
  xmlChar *key;
  gchar *xpmdir;
  xpmdir = strdup(XPMDIR);
  cur = cur->xmlChildrenNode;
  
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"termxpm")))
		  {
			 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
			 termPtr[0].termxpm =  strdup(key);
			 termPtr[0].termxpm = strcat(xpmdir, termPtr[0].termxpm);
			 cur = cur->parent;
			 parseTermCommand(doc, cur, termPtr);
		  }
		cur = cur->next;
	 }
}

/* Parse name of Terminal command and any command line arguments */
void parseTermName (xmlDocPtr doc, xmlNodePtr cur, termentry *termPtr)
{
  xmlChar *uri;
  cur = cur->xmlChildrenNode;
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"newterm"))) {
		  uri = xmlGetProp(cur, "name");
		  termPtr[0].termname = strdup(uri);
		  xmlFree(uri);
		  parseTermXpm(doc, cur, termPtr);
		}
		cur = cur->next;
	 }
}

/* Parse command line arguments of app*/
void parseCommand (xmlDocPtr doc, xmlNodePtr cur, menuentry *mePtr, int i)
{
  xmlChar *key;
  cur = cur->xmlChildrenNode;
  
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"command"))) 
		  {
			 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
			 mePtr[i].appcommand = strdup(key);
			 xmlFree(key);
		  }
		cur = cur->next;
	 }
}

/* Parse the display name of the application */
void parseApp (xmlDocPtr doc, xmlNodePtr cur, menuentry *mePtr, int i)
{
  xmlChar *uri;
  cur = cur->xmlChildrenNode;
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"app")))
		  {
			 uri = xmlGetProp(cur, "name");
			 mePtr[i].appname = strdup(uri);
			 xmlFree(uri);
			 parseCommand(doc, cur, mePtr, i);
		  }
		cur = cur->next;
	 }
}

/* Find if the app is in a submenu or not */
void parseSubmenu (xmlDocPtr doc, xmlNodePtr cur, menuentry *mePtr, int i)
{
  xmlChar *uri;
  cur = cur->xmlChildrenNode;
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"submenu")))
		  {
			 uri = xmlGetProp(cur, "name");
			 mePtr[i].appsubmenu = strdup(uri);
			 xmlFree(uri);
			 parseApp(doc, cur, mePtr, i);
		  }
		else 
		  {
			 if ((!xmlStrcmp(cur->name, (const xmlChar *)"app"))) 
				{
				  uri = xmlGetProp(cur, "name");
				  mePtr[i].appsubmenu = "";
				  mePtr[i].appname = strdup(uri);
				  xmlFree(uri);
				  parseCommand (doc, cur, mePtr, i);
				}
		  }
		cur = cur->next;
	 }
}
/* Parse the Icon for the Section buttons */
void parseXpm (xmlDocPtr doc, xmlNodePtr cur, menuentry *mePtr, int i)
{
  xmlChar *key;
  gchar  *xpmdir;
  xpmdir = strdup(XPMDIR);
  cur = cur->xmlChildrenNode;
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"xpm")))
		  {
			 key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);

			 mePtr[i].sectionxpm = strdup(key);
			 mePtr[i].sectionxpm = strdup(strcat(xpmdir, mePtr[i].sectionxpm));
			 xmlFree(key);
			 free(xpmdir);
			 cur = cur->parent;
			 parseSubmenu(doc, cur, mePtr, i);
			 i++;
		  }
		cur = cur->next;
	 }
}

/* Find which section the app is in */
void parseSection (xmlDocPtr doc, xmlNodePtr cur, menuentry *mePtr)
{
  int i=0;
  xmlChar *uri;
  cur = cur->xmlChildrenNode;
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"section")))
		  {
			 uri = xmlGetProp(cur, "name");
			 mePtr[i].appsection = strdup(uri);
			 xmlFree(uri);
			 parseXpm(doc, cur, mePtr, i);
			 i++;
		  }
		cur = cur->next;
	 }
}

/* Parse applist.xml - XML file */
void parseDoc(char *docname, menuentry *mePtr, termentry *termPtr)
{
  xmlDocPtr doc;
  xmlNodePtr cur;
  doc = xmlParseFile(docname);
  
  if (doc == NULL ) 
	 fprintf(stderr,"Document not parsed successfully. \n");

  
  cur = xmlDocGetRootElement(doc);
  
  if (cur == NULL) {
	 fprintf(stderr,"empty document\n");
	 xmlFreeDoc(doc);
  }
  
  if (xmlStrcmp(cur->name, (const xmlChar *) "root")) {
	 fprintf(stderr,"document of the wrong type, root node != root");
	 xmlFreeDoc(doc);
  }
  
  while (cur != NULL) 
	 {
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"root")))
		  {
			 parseTermName(doc, cur, termPtr);
			 parseSection(doc, cur, mePtr);
		  }
		cur = cur->next;
	 }
  /*  xmlFreeDoc(doc); */
}

/* function to create or delete start login file */
void start_login (GtkWidget *widget,  gpointer data)
{
  char *msg;
  char autoload[200];
  char menudir[200];
  char *home = strdup(HOMED);
  char *menufile = strdup(MENUFILE);
  char *menud = strdup(MENUD);
  sprintf(menudir, "%s%s", home, menud);
  sprintf(autoload, "%s%s",menudir, menufile);

  if (GTK_TOGGLE_BUTTON (widget)->active) 
	 {
		FILE *fopen(), *fp;
	
		msg = "#####################################################################\n"
		  "#               This file was created by the CMS Menu.              #\n"
		  "#               --------------------------------------              #\n"
		  "# Do not delete this file unless you want the menu to appear every  #\n"
		  "# time you login. If you want to change the way the menu behaves,   #\n"
		  "# open up the menu by typing menu at the shell prompt and go to the #\n"
		  "# options menu in the program.                                      #\n"
		  "#####################################################################\n";
		
		fp = fopen(autoload,"w");
		fprintf(fp,"%s", msg);
		chmod (autoload, 0400);
	 } 
  else {
	 unlink(autoload);
  }
}

static gboolean delete_event( GtkWidget *widget,
										GdkEvent  *event,
										gpointer   data )
{
  return TRUE; 
}

static gint button_press( GtkWidget *widget,
								  GdkEvent *event )
{
  if (event->type == GDK_BUTTON_PRESS) 
	 {
		GdkEventButton *bevent = (GdkEventButton *) event; 
		gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
							 bevent->button, bevent->time);
		/* Tell calling code that we have handled this event; stop here */
		return TRUE;
	 }
  /* Tell calling code that we have not handled this event; pass it on. */
  return FALSE;
}

void destroy( GtkWidget *widget,
				  gpointer   data )
{
  gtk_main_quit();
}

GtkWidget *xpm_menu_box( GtkWidget *parent,
								 gchar     **xpm_arrow,
								 gchar     *xpm_icon,
								 gchar     *label_text)
{
  GtkWidget *box1;
  GtkWidget *box2;
  GtkWidget *box3;
  GtkWidget *label;
  GtkWidget *pixmapwid;
  GdkPixmap *pixmap;
  GdkBitmap *mask;
  GtkWidget *pixmapwid2;
  GdkPixmap *pixmap2;
  GtkStyle *style;
  
  /* Create box for xpm and label */
  box1 = gtk_hbox_new (FALSE, 0);
  box2 = gtk_hbox_new (FALSE, 0);
  box3 = gtk_hbox_new (FALSE, 0);

  gtk_container_set_border_width (GTK_CONTAINER (box1), 0);
  gtk_container_set_border_width (GTK_CONTAINER (box2), 0);
  gtk_container_set_border_width (GTK_CONTAINER (box3), 0);
  style = gtk_widget_get_style(parent); /* Get style of button for background */
  
  pixmap = gdk_pixmap_create_from_xpm_d (parent->window, &mask,
													  &style->bg[GTK_STATE_NORMAL],
													  (gchar **)xpm_arrow);
  pixmapwid = gtk_pixmap_new (pixmap, mask);

  pixmap2 = gdk_pixmap_create_from_xpm (parent->window, &mask,
                                        &style->bg[GTK_STATE_NORMAL],
													 xpm_icon);
  pixmapwid2 = gtk_pixmap_new (pixmap2, mask); 
  label = gtk_label_new (label_text);
  
  /* Pack the pixmap and label into the box */
  gtk_box_pack_start (GTK_BOX (box1), pixmapwid2, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
  gtk_box_pack_end (GTK_BOX (box2), pixmapwid, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (box3), box1, FALSE, FALSE, 0);
  gtk_box_pack_end (GTK_BOX (box3), box2, FALSE, FALSE, 0);
  
  gtk_widget_show(box1);
  gtk_widget_show(box2);
  gtk_widget_show(pixmapwid);
  gtk_widget_show(pixmapwid2);
  gtk_widget_show(label);
  return(box3);
}

static void helpitem_response( gchar *helpfile )
{ /* HELP MENU */
  
  GtkWidget *window;
  GtkWidget *box1;
  GtkWidget *box2;
  GtkWidget *button;
  GtkWidget *separator;
  GtkWidget *table;
  GtkWidget *vscrollbar;
  GtkWidget *text;
  GdkFont *fixed_font;
  gchar *helpdir = strdup(HELPDIR);

  FILE *infile;
  
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_widget_set_usize (window, 300, 250);
  gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
							 GTK_SIGNAL_FUNC(delete_event), NULL);
  gtk_window_set_title (GTK_WINDOW (window), "Common Unix Commands");
  gtk_container_set_border_width (GTK_CONTAINER (window), 0);
  
  box1 = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (window), box1);
  gtk_widget_show (box1);
  
  box2 = gtk_vbox_new (FALSE, 10);
  gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
  gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
  gtk_widget_show (box2);
  
  table = gtk_table_new (2, 2, FALSE);
  gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
  gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
  gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
  gtk_widget_show (table);
  
  /* Create the GtkText widget */
  text = gtk_text_new (NULL, NULL);
  gtk_text_set_editable (GTK_TEXT (text), FALSE);
  gtk_text_set_word_wrap (GTK_TEXT (text), TRUE);
  gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
						  GTK_EXPAND | GTK_SHRINK | GTK_FILL,
						  GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
  gtk_widget_show (text);
  
  /* Add a vertical scrollbar to the GtkText widget */
  vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
  gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
						  GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
  gtk_widget_show (vscrollbar);
  
  /* Load a fixed font */
  fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-120-*-*-*-*-*-*");
  
  gtk_widget_realize (text);
  
  /* Freeze the text widget, ready for multiple updates */
  gtk_text_freeze (GTK_TEXT (text));
  
  /* Load the file text.c into the text window */

  helpdir = strcat(helpdir, helpfile);  
  infile = fopen(helpdir, "r");

  if (infile) {
	 char buffer[1024];
	 int nchars;
	 
	 while (1)
		{
		  nchars = fread(buffer, 1, 1024, infile);
		  gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
								 NULL, buffer, nchars);
		  if (nchars < 1024)
			 break;
		}
	 fclose (infile);
  }
  gtk_text_thaw (GTK_TEXT (text)); /* Thaw. Make updates available on screen */
  
  separator = gtk_hseparator_new ();
  gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
  gtk_widget_show (separator);
  
  box2 = gtk_vbox_new (FALSE, 10);
  gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
  gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
  gtk_widget_show (box2);
  
  button = gtk_button_new_with_label ("Close");
  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
									  GTK_SIGNAL_FUNC (gtk_widget_destroy),
									  GTK_OBJECT (window));
  gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
  GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  gtk_widget_grab_default (button);
  gtk_widget_show (button);
  
  gtk_widget_show (window);
}

static void option_response( gchar *string )
{ /* OPTIONS MENU */
  GtkWidget *window;
  GtkWidget *box1;
  GtkWidget *box2;
  GtkWidget *box3;
  GtkWidget *separator;
  GtkWidget *button;
  GtkWidget *label;
  GtkWidget *frame;
  GSList *group;
  char autoload[200];
  char menudir[200];
  char *home = strdup(HOMED);
  char *menufile = strdup(MENUFILE);
  char *menud = strdup(MENUD);
  sprintf(menudir, "%s%s", home, menud);
  sprintf(autoload, "%s%s", menudir, menufile); 

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
							 GTK_SIGNAL_FUNC(delete_event), NULL);
  gtk_window_set_title (GTK_WINDOW (window), "Unix@CMS Menu Options");
  gtk_container_set_border_width (GTK_CONTAINER (window), 4);
  
  box1 = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (window), box1);
  gtk_widget_show (box1);
  
  frame = gtk_frame_new ("Start at Login");	
  
  box2 = gtk_vbox_new (FALSE, 0);
  gtk_container_set_border_width (GTK_CONTAINER (box2), 2);
  gtk_container_add (GTK_CONTAINER (frame), box2);
  gtk_widget_show (box2); 
  
  label = gtk_label_new ("You can start the menu manually by typing menu at the" 
								 " shell prompt if you disable the \"Start At Login\" feature.");
  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
  
  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
  gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
  gtk_widget_show (label);	
  
  separator = gtk_menu_item_new ();
  gtk_box_pack_start (GTK_BOX (box2), separator, FALSE, FALSE, 0);
  gtk_widget_show (separator);
  
  box3 = gtk_hbox_new (FALSE, 0);
  gtk_box_pack_start (GTK_BOX (box2), box3, FALSE, FALSE, 0);
  gtk_widget_show (box3);
  
  button = gtk_radio_button_new_with_label (NULL, "Start At Login");
  gtk_box_pack_start (GTK_BOX (box3), button, FALSE, FALSE, 0);
  gtk_widget_show (button);
  
  group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
  button = gtk_radio_button_new_with_label(group, "Dont Start At Login");
  if(access(autoload, F_OK) == 0) 
	 {
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
	 }
  else 
	 {
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
	 }
  
  gtk_signal_connect (GTK_OBJECT (button), "toggled",
							 GTK_SIGNAL_FUNC(start_login), NULL);
  gtk_box_pack_start (GTK_BOX (box3), button, FALSE, FALSE, 0);
  gtk_widget_show (button);
  
  gtk_box_pack_start (GTK_BOX (box1), frame, FALSE, FALSE, 0);
  gtk_widget_show (frame); 
  
  button = gtk_button_new_with_label ("Close");
  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
									  GTK_SIGNAL_FUNC (gtk_widget_destroy),
									  GTK_OBJECT (window));
  gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
  GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  gtk_widget_grab_default (button);
  gtk_widget_show (button);
  gtk_widget_show (window);	
}

void checkChild(int sigint_flag)
{
  if (sigint_flag) 
	 kill (getpid(), SIGINT);  
}

void execute(char ** args)
{
  pid_t pid;
  int sigint_flag = 0;

  pid = fork();  /* spawn a child process */
  
  switch(pid) 
    {
    case -1:
		exit(1);
    case 0:
		checkChild(sigint_flag);
		break;
	 default:
		execvp(*args, args);
		break;
    }
}

void parse(char * buf, char **args)
{
  while (*buf != NULL) {
	 /* Strip whitespace.  Use nulls, so previous argument is terminated */
	 while ((*buf == ' ') || (*buf == '\t')) 
		*buf++ = NULL;
	 
	 /* Save the argument. */
	 *args++ = buf;
	 
	 /* Skip over the argument.  */
	 while ((*buf != NULL) && (*buf != ' ') && (*buf != '\t'))
		buf++;
  }
  *args = NULL;
}

static void item_response( GtkObject *passme )
{ /* Execute Apps */
  char *buf;
  char *sec;
  char *args[64];
  buf = strdup(gtk_object_get_data(passme, "command_key"));
  sec = strdup(gtk_object_get_data(passme, "section_key"));

  if (strcmp(sec, "Help") != 0)
	 {
		parse(buf, args);
		execute(args);
	 }
  else 
	 {
		helpitem_response(buf);
	 }
}


static void make_window(menuentry *mePtr, termentry *termPtr, int n)
{
  gint numSubs = countSubmenus(APPLIST);
  gint numSections = countSections(APPLIST);
  GtkWidget *submenu[numSubs], *sectionmenu[numSections], *window, *menu_items, *vbox, *hbox, *button;
  GtkTooltips *tooltips;
  gint sectionButton[numSections], i, getSecs = 0, getSubs = 0;
  gchar buf[128], *done = "", *doneSection = "null";
  gchar *optionxpm = strdup(XPMDIR);
  gchar *quitxpm = strdup(XPMDIR);
  optionxpm = strcat(optionxpm, "options.xpm");
  quitxpm = strcat(quitxpm, "logout.xpm");
  
  for (i=0; i< numSections; i++) 
	 sectionmenu[i] = gtk_menu_new();
  
  for (i=0; i< numSubs; i++) 
	 submenu[i] = gtk_menu_new();
  
  for (i=0; i < numSections; i++) 
	 sectionButton[i] = 0;
  
  /* create a new window */
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Unix@CMS");
  gtk_signal_connect (GTK_OBJECT (window), "delete_event",
							 (GtkSignalFunc) gtk_main_quit, NULL);
  gtk_widget_realize(window);
  
  vbox = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (window), vbox);
  gtk_widget_show (vbox);
  
  /* NEW TERMINAL BUTTON */
  button = gtk_button_new();
  gtk_object_set_data(GTK_OBJECT (button), "command_key", termPtr[0].termcmd);
  gtk_object_set_data(GTK_OBJECT (button), "section_key", mePtr[i].appsection);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
							 GTK_SIGNAL_FUNC (item_response), button);
  
  hbox = xpm_menu_box(window, no_xpm, termPtr[0].termxpm, termPtr[0].termname);
  gtk_widget_show(hbox);
  gtk_container_add (GTK_CONTAINER (button), hbox);
  gtk_widget_show(button);
  gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
  
  /* BEGIN BUILDING TOP LEVEL BUTTONS */
  for (i = 0; i < n; i++) 
	 {
		if ((strcmp(doneSection, mePtr[i].appsection) != 0)) 
		  {
			 button = gtk_button_new();
			 gtk_signal_connect_object (GTK_OBJECT (button), "event",
												 GTK_SIGNAL_FUNC (button_press), GTK_OBJECT (sectionmenu[getSecs]));
			 hbox = xpm_menu_box(window, r_arrow_xpm, mePtr[i].sectionxpm, mePtr[i].appsection);
			 gtk_widget_show(hbox);
			 gtk_container_add (GTK_CONTAINER (button), hbox);
			 gtk_widget_show(button);
			 gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
			 gtk_widget_show (button);
			 getSecs++;
			 doneSection =  mePtr[i].appsection;
		  }
		if (strcmp(mePtr[i].appsubmenu, ""))  /* There is a sub menu */
			 {
				if (strcmp(done, mePtr[i].appsubmenu)) /* already done submenu label */
				  { 
					 getSubs++;
					 sprintf (buf, mePtr[i].appsubmenu);
					 menu_items = gtk_menu_item_new_with_label (buf);
					 gtk_widget_set_name (menu_items, "menu_items");
					 gtk_container_add (GTK_CONTAINER (sectionmenu[getSecs-1]), menu_items);
					 gtk_widget_show (menu_items);
					 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_items), submenu[getSubs]);
					 done = mePtr[i].appsubmenu; /* Make submenus unique */
				  }
				if (strcmp(done, mePtr[i].appname)) /* App in submenu */
				  {
					 sprintf (buf, mePtr[i].appname);
					 menu_items = gtk_menu_item_new_with_label (buf);
					 gtk_menu_append (GTK_MENU (submenu[getSubs]), menu_items);
					 /* Find number of args */
					 gtk_object_set_data(GTK_OBJECT (menu_items), "command_key", mePtr[i].appcommand);
					 gtk_object_set_data(GTK_OBJECT (menu_items), "section_key", mePtr[i].appsection);
					 gtk_signal_connect (GTK_OBJECT (menu_items), "activate",
												GTK_SIGNAL_FUNC (item_response),	menu_items);
					 gtk_widget_show (menu_items);
				  }
			 }
		  else /* no submenu */
			 {
				if (strcmp(done, mePtr[i].appname)) 
				  {
					 sprintf (buf, mePtr[i].appname);
					 menu_items = gtk_menu_item_new_with_label (buf);
					 gtk_menu_append (GTK_MENU (sectionmenu[getSecs-1]), menu_items);
					 gtk_object_set_data(GTK_OBJECT (menu_items), "command_key", mePtr[i].appcommand);
					 gtk_object_set_data(GTK_OBJECT (menu_items), "section_key", mePtr[i].appsection);
					 gtk_signal_connect (GTK_OBJECT (menu_items), "activate",
												GTK_SIGNAL_FUNC (item_response),	menu_items);
					 gtk_widget_show (menu_items);
				  }
			 }
	 }
  
  button = gtk_button_new();
  tooltips = gtk_tooltips_new ();
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
							 GTK_SIGNAL_FUNC (option_response), (gpointer) "Options");
  hbox = xpm_menu_box(window, no_xpm, optionxpm, "Options");
  gtk_tooltips_set_tip (tooltips, button, "Automatic startup of the menu at login can be disabled by clicking on Options", NULL);
  gtk_widget_show(hbox);
  gtk_container_add (GTK_CONTAINER (button), hbox);
  gtk_widget_show(button);
  gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
  gtk_widget_show (button);
  
  button = gtk_button_new();
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
							 GTK_SIGNAL_FUNC (destroy), (gpointer) "Exit");
  hbox = xpm_menu_box(window, no_xpm, quitxpm, "Quit");
  gtk_widget_show(hbox);
  gtk_container_add (GTK_CONTAINER (button), hbox);
  gtk_widget_show(button);
  gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
  gtk_widget_show (button);
  gtk_widget_show (window);
  gtk_main ();
}

int main( int argc, char *argv[] )
{
  gint c, readrc = 0;
  gint n = countElements(APPLIST);
  menuentry *mePtr = malloc( n * sizeof (menuentry) );
  termentry *termPtr = malloc( 1 * sizeof (menuentry) );
  char autoload[200];
  char menudir[200];
  char *home = strdup(HOMED);
  char *menufile = strdup(MENUFILE);
  char *menud = strdup(MENUD);

  gtk_init (&argc, &argv);
  /* Parse commandline arguments */
  while (--argc > 0 && (*++argv)[0] == '-')
	 while (c = *++argv[0])
		switch (c) 
		  {
		  case 'r': /* started from login script */
			 readrc = 1;
			 break;
		  default:
			 argc = 0; 
			 break;
		  }
  sprintf(menudir, "%s%s", home, menud);
  sprintf(autoload, "%s%s%s", home, menudir, menufile);
  
  if(access(menudir, F_OK) != 0) 
	 mkdir(menudir, 0700);
  
  if (readrc != 1)  /* no arguments were passed */
	 {
		parseDoc(APPLIST, mePtr, termPtr);
		make_window(mePtr, termPtr, n);
	 }
  else  /* The -r option was passed. Need to test if they want to start menu */
	 {
		if(access(autoload, F_OK) == 0) /* Previously select not to start menu */
			 return EXIT_SUCCESS;
		else /* Have selected to start menu */
		  {
			 parseDoc(APPLIST, mePtr, termPtr);
			 make_window(mePtr, termPtr, n);
		  }
	 }
  return EXIT_SUCCESS;
}

[-- Attachment #3: menu.h --]
[-- Type: text/plain, Size: 1225 bytes --]

/* Contains XPM data for arrow and transparent xpm
 * and the location of applist.xml, the xpm files
 * and the help files.
 */

/* THESE NEED TO CHANGE TO REFLECT THE LOCATION OF THE FILES */
#define APPLIST "/home/bm98/prg/gtk-menu/current/applist.xml"
#define XPMDIR "/home/bm98/prg/gtk-menu/current/xpms/"
#define HELPDIR "/home/bm98/prg/gtk-menu/current/help/"
/* END CHANGE */
#define HOMED strdup(getenv("HOME"))
#define MENUD "/.cmsmenu"
#define MENUFILE "/menu-autoload"

static gchar * no_xpm[] = {
"1 1 1 1",
"  c None",
" "};

static char * r_arrow_xpm[] = {
"14 14 26 1",
"  c None",
". c #B1B1B1",
"+ c #404040",
"@ c #323232",
"# c #414141",
"$ c #767676",
"% c #979797",
"& c #000000",
"* c #3B3B3B",
"= c #292929",
"- c #969696",
"; c #242424",
"> c #EBEBEB",
", c #F4F4F4",
"' c #272727",
") c #949494",
"! c #393939",
"~ c #FDFDFD",
"{ c #5F5F5F",
"] c #717171",
"^ c #1B1B1B",
"/ c #D5D5D5",
"( c #515151",
"_ c #B0B0B0",
": c #737373",
"< c #0D0D0D",
"     .+       ",
"     .@#      ",
"     .$%#     ",
"     .$&%#    ",
"*****=$&&-#   ",
";......&&&-#  ",
"'&&&&&&&&&&-# ",
"'&&&&&&&&&&&-]",
"'&&&&&&&&&&-] ",
";......&&&-]  ",
"$$$$$($&&-]   ",
"     _$&-]    ",
"     _:-]     ",
"     _<]      "};

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: segfault with strdup
  2003-05-20 12:25 ` Chris Nanakos
  2003-05-20 12:46   ` Martin Buchan
@ 2003-05-20 13:12   ` Martin Buchan
  1 sibling, 0 replies; 7+ messages in thread
From: Martin Buchan @ 2003-05-20 13:12 UTC (permalink / raw)
  To: linux-c-programming; +Cc: Chris Nanakos

On Tue, May 20, 2003 at 03:25:31PM +0300, Chris Nanakos wrote:
> Can you send the source code???
> 

Here is an excerpt from the XML file as well so you can see what im
dealing with. (Althyough, i dont think it is a libxml problem going
by the errors given back by ddd)


<?xml version="1.0"?>
 <root>
   <newterm name="New Terminal">
     <termxpm>terminal.xpm</termxpm>
     <termcmd>rxvt -fn 6x13 -sb -sl 1000 -T Unix@CMS</termcmd>
   </newterm>
   <section name="Internet">
     <xpm>browsers.xpm</xpm>
     <submenu name="Web Browsers">
       <app name="Mozilla Web Broswer">
         <command>mozilla http://unix.cms.gre.ac.uk</command>
       </app>
     </submenu>
   </section>
   <section name="Internet">
     <xpm>browsers.xpm</xpm>
     <submenu name="Web Browsers">
       <app name="Netscape Navigator">
         <command>netscape http://unix.cms.gre.ac.uk</command>
       </app>
     </submenu>
   </section>
   <section name="Internet">
     <xpm>browsers.xpm</xpm>
     <submenu name="Web Browsers">
       <app name="Lynx Text Only Browser">
         <command>rxvt -fn 6x13 -e lynx http://unix.cms.gre.ac.uk</command>
       </app>
     </submenu>
   </section>
  
<...snipped...>
  
  
It fails on "Netscape Navigator" when i install to a different directory than 
/home/bm98/prg/gtk-menu/current

If i change it to Netscape, it then works but fails on "Lynx Text Only Browser" and so on.

However, it all works if i run it in /home/bm98/prg/gtk-menu/current

Martin

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: segfault with strdup
       [not found] ` <200305201316.h4KDGUhG007842@grinch.txt.com>
@ 2003-05-20 13:52   ` Martin Buchan
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Buchan @ 2003-05-20 13:52 UTC (permalink / raw)
  To: linux-c-programming; +Cc: Jason P. Winters

On Tue, May 20, 2003 at 06:15:58AM -0700, Jason P. Winters wrote:
>  
> > The place where it is seg faulting is
> > 
> > uri = xmlGetProp(cur, "name");
> > mePtr[i].appname = strdup(uri);  /* HERE */
> 
> Well, I don't have a lot of time to spend on it, but here are a
> couple of observations:
> 
> First and formost: you're not testing the result of xmlGetProp for
> null. This is probably your "problem", as you then try and dup a
> null string.  Bad habit, that. :}

Point taken :-)
Now i am testing for NULL but i still get the same problem. However,
i do not think this is the probelm because if i step thru the
program with ddd, just before it segfaults at the line 

mePtr[i].appname = strdup(uri);

If i hover the mouse over the previous line:

uri = xmlGetProp(cur, "name");

It shows me that the value of uri is "Netscape Navigator"

Also, if this was the case (and i wish it was cos then i could fix
it :) then that would apply to the directory where the code works in
as well as any other directory.??

thanks for pointing out testing for NULL though.

Martin

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: segfault with strdup
  2003-05-20 11:20 segfault with strdup Martin Buchan
  2003-05-20 12:25 ` Chris Nanakos
       [not found] ` <200305201316.h4KDGUhG007842@grinch.txt.com>
@ 2003-05-20 16:32 ` Glynn Clements
  2003-05-21  9:50   ` Martin Buchan
  2 siblings, 1 reply; 7+ messages in thread
From: Glynn Clements @ 2003-05-20 16:32 UTC (permalink / raw)
  To: Martin Buchan; +Cc: linux-c-programming


Martin Buchan wrote:

> This is all working now, however, it only works if i run it in the
> directory that i have done all my coding in. I.e. If i compile and
> install to a different location, i get a seg fault when parsing the
> XML file. Its not that it cant find the file, it goes thru and
> parses the first entry in the file and then croaks on the 2nd
> while parsing the name of the app - which is "Netscape Navigator"
> If i shorten the name to just "Netscape", it then croaks on the 3rd
> entry which is "Lynx Text Only Browser", if i then shorten this to
> just "Lynx Browser", it then croaks on the 4th and so on and so on.

There is a problem in parseTermXpm:

144	gchar *xpmdir;
145	xpmdir = strdup(XPMDIR);
	...
154	termPtr[0].termxpm = strcat(xpmdir, termPtr[0].termxpm);

The buffer which is being allocated isn't guaranteed to be any larger
than XPMDIR itself (in practice it may be slightly larger due to
padding, but you can't rely on it), so the strcat() call is corrupting
the heap.

Once you corrupt the heap, all bets are off; usually what happens is
that a later call to a heap-management function (malloc, calloc, free
etc) will segfault.

You are also doing exactly the same thing with HELPDIR.

The most obvious solution is:

	gchar *xpmdir;
	xpmdir = malloc(strlen(XPMDIR) + strlen(termPtr[0].termxpm) + 1);
	strcpy(xpmdir, XPMDIR);
	...
	termPtr[0].termxpm = strcat(xpmdir, termPtr[0].termxpm);

-- 
Glynn Clements <glynn.clements@virgin.net>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: segfault with strdup
  2003-05-20 16:32 ` Glynn Clements
@ 2003-05-21  9:50   ` Martin Buchan
  0 siblings, 0 replies; 7+ messages in thread
From: Martin Buchan @ 2003-05-21  9:50 UTC (permalink / raw)
  To: linux-c-programming; +Cc: Glynn Clements

On Tue, May 20, 2003 at 05:32:39PM +0100, Glynn Clements wrote:
> 
> There is a problem in parseTermXpm:
> 
> 144	gchar *xpmdir;
> 145	xpmdir = strdup(XPMDIR);
> 	...
> 154	termPtr[0].termxpm = strcat(xpmdir, termPtr[0].termxpm);
> 
> The buffer which is being allocated isn't guaranteed to be any larger
> than XPMDIR itself (in practice it may be slightly larger due to
> padding, but you can't rely on it), so the strcat() call is corrupting
> the heap.
> 
> Once you corrupt the heap, all bets are off; usually what happens is
> that a later call to a heap-management function (malloc, calloc, free
> etc) will segfault.
> 
> You are also doing exactly the same thing with HELPDIR.
> 
> The most obvious solution is:
> 
> 	gchar *xpmdir;
> 	xpmdir = malloc(strlen(XPMDIR) + strlen(termPtr[0].termxpm) + 1);
> 	strcpy(xpmdir, XPMDIR);
> 	...
> 	termPtr[0].termxpm = strcat(xpmdir, termPtr[0].termxpm);

This highlights my fundamental misunderstanding of memory management
in C :-( (I come from lightweight langs like perl where i dont need
to worry about this stuff)

However, this has given me a better grasp of where i am going wrong
and now i realise that i was very lucky to get the prog to work at
all in the first place as I am doing this kind of thing all over the
place.

I tried as you suggested and it cured that problem but has given
birth to more problems of the same ilk i think. Now i know where i
am going wrong though so hopefully i can fix them. (Although i
havent yet :-)

Thanks again

Martin

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2003-05-21  9:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-05-20 11:20 segfault with strdup Martin Buchan
2003-05-20 12:25 ` Chris Nanakos
2003-05-20 12:46   ` Martin Buchan
2003-05-20 13:12   ` Martin Buchan
     [not found] ` <200305201316.h4KDGUhG007842@grinch.txt.com>
2003-05-20 13:52   ` Martin Buchan
2003-05-20 16:32 ` Glynn Clements
2003-05-21  9:50   ` Martin Buchan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).