linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Martin Buchan <M.J.Buchan@gre.ac.uk>
To: linux-c-programming@vger.kernel.org
Cc: Chris Nanakos <nanakos@wired-net.gr>
Subject: Re: segfault with strdup
Date: Tue, 20 May 2003 13:46:13 +0100	[thread overview]
Message-ID: <20030520124613.GB674@gre.ac.uk> (raw)
In-Reply-To: <002d01c31ecb$8c947600$852005d5@carlos>

[-- 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",
"     .+       ",
"     .@#      ",
"     .$%#     ",
"     .$&%#    ",
"*****=$&&-#   ",
";......&&&-#  ",
"'&&&&&&&&&&-# ",
"'&&&&&&&&&&&-]",
"'&&&&&&&&&&-] ",
";......&&&-]  ",
"$$$$$($&&-]   ",
"     _$&-]    ",
"     _:-]     ",
"     _<]      "};

  reply	other threads:[~2003-05-20 12:46 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-05-20 11:20 segfault with strdup Martin Buchan
2003-05-20 12:25 ` Chris Nanakos
2003-05-20 12:46   ` Martin Buchan [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030520124613.GB674@gre.ac.uk \
    --to=m.j.buchan@gre.ac.uk \
    --cc=linux-c-programming@vger.kernel.org \
    --cc=nanakos@wired-net.gr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).