/*****************************************************************************/
/*  misc.c - general purpose routines                                        */
/*  Copyright (C) 1998 Brian Masney <masneyb@newwave.net>                    */
/*                                                                           */
/*  This program is free software; you can redistribute it and/or modify     */
/*  it under the terms of the GNU General Public License as published by     */
/*  the Free Software Foundation; either version 2 of the License, or        */
/*  (at your option) any later version.                                      */
/*                                                                           */
/*  This program 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 General Public License for more details.                             */
/*                                                                           */
/*  You should have received a copy of the GNU General Public License        */
/*  along with this program; if not, write to the Free Software              */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
/*****************************************************************************/

#include "ftp.h"

extern struct conn_categories *hostcat;
extern struct pix_ext *registered_exts;
extern char emailaddr[MAXSTR];

extern GdkPixmap *dotdot_pixmap, *dir_pixmap, *linkdir_pixmap, *linkfile_pixmap,
   *exe_pixmap, *doc_pixmap;
extern GdkBitmap *dotdot_mask, *dir_mask, *linkdir_mask, *linkfile_mask, 
   *exe_mask, *doc_mask;
      
void *mymalloc(size_t size) {
   void *mem;
   
   if((mem = malloc(size)) == NULL) {
      printf("\nError allocating memory. This FTP program will be shut down\n");
      exit(0);
   }
   else return(mem);
}
/*****************************************************************************/
void *myrealloc(void *ptr, size_t size) {
   void *mem;
   
   if((mem = realloc(ptr, size)) == NULL) {
      printf("\nError allocating memory. This FTP program will be shut down\n");
      exit(0);
   }
   else return(mem);
}
/*****************************************************************************/
char *insert_commas(unsigned long number, char *dest, int size) {
   char *frompos, *topos;
   char src[MAXSTR];
   int num, rem, i;
   
   snprintf(src, sizeof(src), "%ld", number);
   src[sizeof(src)-1] = '\0';
   num = strlen(src) / 3 - 1;
   rem = strlen(src) % 3;
   if(strlen(src) + num + (rem == 0 ? 0 : 1) + 1 > size) {
      if(strlen(src) < size) strncpy(dest, src, size-1);
      else memset(dest, 'X', size-1);
      dest[size-1] = '\0';
      return(dest);
   }
   frompos = src;
   topos = dest;
   for(i=0; i<rem; i++) *topos++ = *frompos++;
   if(*frompos != '\0') {
      if(rem != 0) *topos++ = ',';
      while(num > 0) {
         for(i=0; i<3; i++) *topos++ = *frompos++;
         *topos++ = ',';
         num--;
      }
      for(i=0; i<3; i++) *topos++ = *frompos++;
   }
   *topos = '\0';
   return(dest);
}
/*****************************************************************************/
void add_local_files(struct ftp_window_data *wdata) {
   struct ftp_file_data *fle;
   struct stat st;
   char tempstr[MAXSTR];
   FILE *dir;
   int isdotdot = 0, i;

   gtk_clist_freeze(GTK_CLIST(wdata->listbox));
   wdata->local = 1;
   wdata->totalitems = wdata->numselected = 0;
   dir = popen("/bin/ls -al", "r");
   while(fgets(tempstr, sizeof(tempstr), dir)) {
      fle = mymalloc(sizeof(struct ftp_file_data));
      tempstr[strlen(tempstr)-1] = '\0';
      if(ftp_parse_file_listing(fle, tempstr) && strcmp(fle->file, ".") != 0) {
         if(strcmp(fle->file, "..") == 0) isdotdot = 1;
         stat(fle->file, &st);
         fle->isdir = S_ISDIR(st.st_mode);
         fle->isexe = (strchr(fle->attribs, 'x') != NULL) && !fle->isdir;
         fle->islink = fle->attribs[0] == 'l';
         add_file_listbox(wdata, fle);
         fle->next = NULL;
         if(wdata->host->last == NULL) wdata->host->files = fle;
         else wdata->host->last->next = fle;
         wdata->host->last = fle;  
         wdata->totalitems++;
      }
      else free(fle);
   }
   pclose(dir);
   if(!isdotdot) {
      fle = mymalloc(sizeof(struct ftp_file_data));
      strcpy(fle->file, "..");
      fle->size = 0;
      fle->user[0] = fle->group[0] = fle->attribs[0] = fle->dt[0] = '\0';
      fle->next = NULL;
      if(wdata->host->last == NULL) wdata->host->files = fle;
      else wdata->host->last->next = fle;
      add_file_listbox(wdata, fle);
      wdata->totalitems++;
   }
   strncpy(wdata->host->dir, getcwd(tempstr, sizeof(tempstr)), sizeof(wdata->host->dir));
   update_ftp_info(wdata);
   wdata->host->dir[sizeof(wdata->host->dir)-1] = '\0';
   if(wdata->items) wdata->items = myrealloc(wdata->items, sizeof(int)*wdata->totalitems);
   else wdata->items = mymalloc(sizeof(int)*wdata->totalitems);
   for(i=0; i<wdata->totalitems; i++) wdata->items[i] = 0;
   sortrows(GTK_CLIST(wdata->listbox), wdata->sortcol, (gpointer) wdata);
   gtk_clist_thaw(GTK_CLIST(wdata->listbox));
}
/*****************************************************************************/
void add_file_listbox(struct ftp_window_data *wdata, struct ftp_file_data *fle) {
   char *add_data[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
   struct pix_ext *tempext;
   size_t stlen;
   gint num;

   stlen = strlen(fle->file);
   num = gtk_clist_append(GTK_CLIST(wdata->listbox), add_data);
   if(strcmp(fle->file, "..") == 0) {
      gtk_clist_set_pixmap(GTK_CLIST(wdata->listbox), num, 0, dotdot_pixmap, dotdot_mask);
   }
   else if(fle->islink && fle->isdir) {
      gtk_clist_set_pixmap(GTK_CLIST(wdata->listbox), num, 0, linkdir_pixmap, linkdir_mask);
   }
   else if(fle->islink) {
      gtk_clist_set_pixmap(GTK_CLIST(wdata->listbox), num, 0, linkfile_pixmap, linkfile_mask);
   }
   else if(fle->isdir) {
      gtk_clist_set_pixmap(GTK_CLIST(wdata->listbox), num, 0, dir_pixmap, dir_mask);
   }
   else if(fle->isexe) {
      gtk_clist_set_pixmap(GTK_CLIST(wdata->listbox), num, 0, exe_pixmap, exe_mask);
   }
   else {
      tempext = registered_exts;
      while(tempext != NULL) {
         if(stlen >= tempext->stlen &&
            strcmp(&fle->file[stlen-tempext->stlen], tempext->ext) == 0) {

            gtk_clist_set_pixmap(GTK_CLIST(wdata->listbox), num, 0, tempext->pixmap, tempext->mask);
            break;
         }
         tempext = tempext->next;
      }
      if(tempext == NULL) {
         gtk_clist_set_pixmap(GTK_CLIST(wdata->listbox), num, 0, doc_pixmap, doc_mask);
      }
   }
   gtk_clist_set_text(GTK_CLIST(wdata->listbox), num, 1, fle->file);
   gtk_clist_set_text(GTK_CLIST(wdata->listbox), num, 2, fle->strsize);
   gtk_clist_set_text(GTK_CLIST(wdata->listbox), num, 3, fle->user);
   gtk_clist_set_text(GTK_CLIST(wdata->listbox), num, 4, fle->group);
   gtk_clist_set_text(GTK_CLIST(wdata->listbox), num, 5, fle->dt);
   gtk_clist_set_text(GTK_CLIST(wdata->listbox), num, 6, fle->attribs);
}
/*****************************************************************************/
long file_countlf(FILE *filefd, long endpos) {
   char tempstr[MAXSTR];
   long num = 0, curpos, mypos;
   size_t n;
   int i;
            
   curpos = ftell(filefd);
   fseek(filefd, 0, SEEK_SET);
   mypos = 0;
   while((n=fread(tempstr, 1, sizeof(tempstr), filefd)) > 0) {
      for(i=0; i<n; i++) {
         if((tempstr[i] == '\n') && (i > 0) && (tempstr[i-1] != '\r')
            && (endpos == 0 || mypos+i <= endpos)) ++num;
      }
      mypos += n;
   }
   fseek(filefd, curpos, SEEK_SET);
   return(num);
}
/*****************************************************************************/
char *alltrim(char *str) {
   char *pos, *newpos;
   int diff;

   pos = str+strlen(str);
   while(*pos == ' ') *pos-- = '\0';
   
   pos = str;
   diff = 0;
   while(*pos++ == ' ') diff++;

   pos = str+diff;
   newpos = str;
   while(*pos != '\0') *newpos++ = *pos++;
   *newpos = '\0';
   return(str);
}
/*****************************************************************************/
int ftp_parse_file_listing(struct ftp_file_data *fle, char *str) {
   char *startpos, *endpos, tempstr[20];
   int len;

   startpos = str;
   if((endpos = strchr(startpos, ' ')) == NULL) return(0);
   len = endpos - startpos > sizeof(fle->attribs) ? sizeof(fle->attribs) : endpos - startpos + 1;
   strncpy(fle->attribs, startpos, len);
   fle->attribs[len-1] = '\0';
   
   startpos = endpos + 1;
   while(*startpos == ' ') startpos++;
   if((startpos = strchr(startpos, ' ')) == NULL) return(0);
   while(*startpos == ' ') startpos++;
   
   if((endpos = strchr(startpos, ' ')) == NULL) return(0);
   len = endpos - startpos > sizeof(fle->user) ? sizeof(fle->user) : endpos - startpos + 1;
   strncpy(fle->user, startpos, len);
   fle->user[len-1] = '\0';

   startpos = endpos + 1;
   while(*startpos == ' ') startpos++;
   if((endpos = strchr(startpos, ' ')) == NULL) return(0);
   len = endpos - startpos > sizeof(fle->group) ? sizeof(fle->group) : endpos - startpos + 1;
   strncpy(fle->group, startpos, len);
   fle->group[len-1] = '\0';

   startpos = endpos + 1;
   while(*startpos == ' ') startpos++;
   if(fle->attribs[0] == 'b' || fle->attribs[0] == 'c') {
      if((endpos = strchr(startpos, ',')) == NULL) return(0);
      endpos++;
      while(*endpos == ' ') endpos++;
      if((endpos = strchr(endpos, ' ')) == NULL) return(0);
   }
   else {
      if((endpos = strchr(startpos, ' ')) == NULL) return(0);
   }
   len = endpos - startpos > sizeof(fle->strsize) ? sizeof(fle->strsize) : endpos - startpos + 1;
   strncpy(tempstr, startpos, len);
   tempstr[len-1] = '\0';
   if(fle->attribs[0] == 'b' || fle->attribs[0] == 'c') {
      fle->size = 0;
      strncpy(fle->strsize, tempstr, sizeof(fle->strsize));
   }
   else {
      fle->size = strtol(tempstr, (char **) NULL, 10);
      insert_commas(fle->size, fle->strsize, sizeof(fle->strsize));
   }
   
   startpos = endpos + 1;
   while(*startpos == ' ') startpos++;
   if((endpos = strchr(startpos, ' ')) == NULL) return(0);
   while(*endpos == ' ') endpos++;
   if((endpos = strchr(endpos, ' ')) == NULL) return(0);
   while(*endpos == ' ') endpos++;
   if((endpos = strchr(endpos, ' ')) == NULL) return(0);
   len = endpos - startpos > sizeof(fle->strsize) ? sizeof(fle->strsize) : endpos - startpos + 1;
   strncpy(fle->dt, startpos, len);
   fle->dt[len-1] = '\0';

   startpos = endpos + 1;
   while(*startpos == ' ') startpos++;
   len = endpos - startpos > sizeof(fle->file) ? sizeof(fle->file) : endpos - startpos + 1;
   strncpy(fle->file, startpos, len);
   fle->file[len-1] = '\0';
   if(fle->attribs[0] == 'l') {
      startpos = strchr(fle->file, '-');
      while(startpos != NULL) {
         if(*(startpos+1) == '>' && *(startpos-1) == ' ') {
            *(startpos-1) = '\0';
            break;
         }
         startpos = strchr(startpos+1, '-');
      }
   }
   return(1);
}
/*****************************************************************************/
void read_config_file(void) {
   struct conn_categories *newcat, *tempcat, *prevcat;
   struct conn_hosts *newhost, *temphost, *prevhost;
   struct pix_ext *tempext;
   struct stat st;
   char tempstr[MAXSTR], temp1str[MAXSTR], category[MAXSTR], *curpos;
   FILE *conffile;
   int line=0;
   
   hostcat = NULL;
   newhost = NULL;
   registered_exts = NULL;
   if(!expand_path(CONFIG_FILE, tempstr, sizeof(tempstr))) {
      printf("Error: Bad config file name %s\n", CONFIG_FILE);
      exit(0);
   }
   stat(tempstr, &st);
   st.st_mode &= 0xFFF;
   if(st.st_mode != 0x180) {
      printf("Config file %s doesn't have proper permissions\nPlease type chmod 0600 %s\n", tempstr, tempstr);
      exit(0);
   }
   conffile = fopen(tempstr, "r");
   if(conffile == NULL) {
      printf("Error: Cannot open config file %s: %s\n", CONFIG_FILE, sys_errlist[errno]);
      exit(0);
   }
   while(fgets(tempstr, sizeof(tempstr), conffile)) {
      tempstr[strlen(tempstr)-1] = '\0';
      line++;
      if(strncmp(tempstr, "email=", 6) == 0) {
         if(strcmp(emailaddr, "") != 0) {
            printf("Error in config file line %d: %s\nCan only have 1 email address in the config file\n", line, tempstr);
            exit(0);
         }
         curpos = tempstr+6;
         parse_args(curpos, 1, line, emailaddr, sizeof(emailaddr));
      }
      else if(strncmp(tempstr, "host=", 5) == 0) {
         newhost = mymalloc(sizeof(struct conn_hosts));
         curpos = tempstr+5;
         parse_args(curpos, 7, line,
            category, sizeof(category),
            newhost->hostdescr, sizeof(newhost->hostdescr),
            newhost->hostname, sizeof(newhost->hostname),
            newhost->port, sizeof(newhost->port),
            newhost->dir, sizeof(newhost->dir),
            newhost->user, sizeof(newhost->user),
            newhost->pass, sizeof(newhost->pass));
         newhost->next = NULL;
         if(strcmp(category, "") == 0 || strcmp(newhost->hostdescr, "") == 0) {
            printf("Error in config file on line %d: You must specify a category and a host\ndescription.\n", line);
            exit(0);
         }
         tempcat = prevcat = hostcat;          
         while(tempcat != NULL) {
            if(strcmp(tempcat->name, category) == 0) {
               temphost = prevhost = tempcat->hosts;
               while(temphost != NULL) {
                  if(strcmp(temphost->hostdescr, newhost->hostdescr) > 0) {
                     newhost->next = temphost;
                     if(temphost == prevhost) tempcat->hosts = newhost;
                     else prevhost->next = newhost;
                     break;
                  }
                  else {
                     prevhost = temphost;
                     temphost = temphost->next;
                  }
               }
               if(temphost == NULL) {
                  prevhost->next = newhost;
                  newhost->next = NULL;
               }
               break;
            }
            else if(strcmp(tempcat->name, category) > 0) {
               newcat = mymalloc(sizeof(struct conn_categories));
               newcat->next = tempcat;
               if(prevcat == tempcat) hostcat = newcat;
               else prevcat->next = newcat;
               strncpy(newcat->name, category, sizeof(newcat->name));
               newcat->name[sizeof(newcat->name)-1] = '\0';
               newcat->hosts = newhost;
               break;
            }
            prevcat = tempcat;
            tempcat = tempcat->next;
         }
         if(tempcat == NULL) {
            newcat = mymalloc(sizeof(struct conn_categories));
            if(hostcat == NULL) {
               newcat->next = hostcat;
               hostcat = newcat;
            }
            else {
               newcat->next = prevcat->next;;
               prevcat->next = newcat;
            }
            strncpy(newcat->name, category, sizeof(newcat->name));
            newcat->name[sizeof(newcat->name)-1] = '\0';
            newcat->hosts = newhost;
         }
      }
      else if(strncmp(tempstr, "ext=", 4) == 0) {
         curpos = tempstr+4;
         tempext = mymalloc(sizeof(struct pix_ext));
         parse_args(curpos, 2, line, 
            tempext->ext, sizeof(tempext->ext),
            tempext->filename, sizeof(tempext->filename));
         snprintf(tempstr, sizeof(tempstr), "%s/%s", BASE_CONF_DIR, tempext->filename);
         tempstr[sizeof(tempstr)-1] = '\0';
         expand_path(tempstr, temp1str, sizeof(temp1str));
         if(stat(temp1str, &st) == -1) {
            printf("Error on line %d: %s doesn't exist\n", line, tempext->filename);
            exit(0);
         }
         tempext->stlen = strlen(tempext->ext);
         tempext->next = registered_exts;
         registered_exts = tempext;
      }         
      else {
         printf("Warning: Skipping line %d in config file\n", line);
      }
   }
   return;
}
/*****************************************************************************/
void write_config_file(void) {
   struct conn_categories *tempcat;
   struct conn_hosts *temphost;
   struct pix_ext *tempext;
   char tempstr[MAXSTR];
   FILE *conffile;

   if(!expand_path(CONFIG_FILE, tempstr, sizeof(tempstr))) {
      printf("Error: Bad config file name %s\n", CONFIG_FILE);
      exit(0);
   }
   conffile = fopen(tempstr, "w+");
   if(conffile == NULL) {
      printf("Error: Cannot open config file %s: %s\n", CONFIG_FILE, sys_errlist[errno]);
      exit(0);
   }
   snprintf(tempstr, sizeof(tempstr), "email=%s\n", emailaddr);
   tempstr[sizeof(tempstr)-1] = '\0';
   fwrite(tempstr, 1, strlen(tempstr), conffile);

   tempcat = hostcat;
   while(tempcat != NULL) {
      temphost = tempcat->hosts;
      while(temphost != NULL) {
         snprintf(tempstr, sizeof(tempstr), "host=%s:%s:%s:%s:%s:%s:%s\n", tempcat->name, 
            temphost->hostdescr, temphost->hostname, temphost->port, temphost->dir, 
            temphost->user, temphost->pass);
         tempstr[sizeof(tempstr)-1] = '\0';
         fwrite(tempstr, 1, strlen(tempstr), conffile);
         temphost = temphost->next;
      }
      tempcat = tempcat->next;
   }
   
   tempext = registered_exts;
   while(tempext != NULL) {
      snprintf(tempstr, sizeof(tempstr), "ext=%s:%s\n", tempext->ext, tempext->filename);
      tempstr[sizeof(tempstr)-1] = '\0';
      fwrite(tempstr, 1, strlen(tempstr), conffile);
      tempext = tempext->next;
   }
   fclose(conffile);
}
/*****************************************************************************/
int expand_path(char *src, char *dest, size_t size) {
   struct passwd *pw;
   char tempstr[20];
   char *pos;
   
   if(strcmp(src, "~") == 0 || strncmp(src, "~/", 2) == 0) pw = getpwuid(getuid());
   else if(strncmp(src, "~", 1) == 0) {
      pos = strchr(src, '/');
      if(pos == NULL) {
         strncpy(tempstr, src+1, sizeof(tempstr));
         tempstr[sizeof(tempstr)-1] = '\0';
      }
      else {
         strncpy(tempstr, src+1, pos-src+1);
         tempstr[pos-src+1] = '\0';
      }
      pw = getpwnam(tempstr);
   }
   else {
      strncpy(dest, src, size-1);
      dest[size-1] = '\0';
      return(1);
   }
   
   if(pw == NULL) {
      *dest = '\0';
      return(0);
   }
   pos = strchr(src, '/');
   if(pos == NULL) {
      strncpy(dest, pw->pw_dir, size-1);
      dest[size-1] = '\0';
      return(1);
   }
   pos++;
   snprintf(dest, size-1, "%s/%s", pw->pw_dir, pos);
   dest[size-1] = '\0';
   return(1);
}
/*****************************************************************************/
int parse_args(char *str, int numargs, int lineno, char *first, ...) {
   char *curpos, *endpos, *dest;
   va_list argp;
   size_t len, newlen;
   
   va_start(argp, first);
   curpos = str;
   
   dest = first;
   len = va_arg(argp, size_t);
   while(numargs > 1) {
      endpos = strchr(curpos, ':');
      if(endpos == NULL) {
         printf("Error in config file on line %d: Not enough arguments\n", lineno);
         exit(0);
      }
      newlen = endpos-curpos > len ? len-1 : endpos-curpos;
      strncpy(dest, curpos, newlen);
      dest[newlen] = '\0';
      curpos = endpos + 1;
      dest = va_arg(argp, char *);
      len = va_arg(argp, size_t);
      numargs--;
   }
   newlen = strlen(curpos) > len-1 ? len-1 : strlen(curpos);
   strncpy(dest, curpos, newlen);
   dest[newlen] = '\0';
   va_end(argp);
   return(1);
}
/*****************************************************************************/
GtkWidget *MakeEditDialog(GtkWidget **dialog, char *diagtxt, char *infotxt, 
   char *oktxt, void (*okfunc)(), void *okptr,
   char *canceltxt, void (*cancelfunc)(), void *cancelptr) {
   
   GtkWidget *text, *edit, *ok, *cancel;
   
   *dialog = gtk_dialog_new();
   gtk_grab_add(*dialog);
   gtk_window_set_title(GTK_WINDOW(*dialog), diagtxt);
   gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(*dialog)->vbox), 10);
   gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(*dialog)->action_area), 5);
   gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(*dialog)->vbox), 5);
   
   text = gtk_label_new(infotxt);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(*dialog)->vbox), text, TRUE, TRUE, FALSE);
   gtk_widget_show(text);
   
   edit = gtk_entry_new_with_max_length(MAXSTR);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(*dialog)->vbox), edit, TRUE, TRUE, FALSE);
   gtk_widget_show(edit);

   ok = gtk_button_new_with_label(oktxt);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(*dialog)->action_area), ok, TRUE, TRUE, FALSE);
   if(okfunc) {
      gtk_signal_connect(GTK_OBJECT(ok), "clicked", GTK_SIGNAL_FUNC(okfunc), (gpointer) okptr);
   }
   gtk_widget_show(ok);
            
   cancel = gtk_button_new_with_label(canceltxt);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(*dialog)->action_area), cancel, TRUE, TRUE, FALSE);
   if(cancelfunc) {
      gtk_signal_connect(GTK_OBJECT(cancel), "clicked", GTK_SIGNAL_FUNC(cancelfunc), (gpointer) cancelptr);
   }
   gtk_widget_show(cancel);

   gtk_widget_show(*dialog);
   return(edit);
}         
/*****************************************************************************/
GtkWidget *MakeYesNoDialog(GtkWidget **dialog, char *diagtxt, char *infotxt, 
   int num, ...) {
   
   GtkWidget *text, *tempwid;
   typedef void (*func)();
   func myfunc;
   va_list argp;
   char *tempstr;
   void *ptr;
   int i;
   
   *dialog = gtk_dialog_new();
   gtk_grab_add(*dialog);
   gtk_window_set_title(GTK_WINDOW(*dialog), diagtxt);
   gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(*dialog)->vbox), 10);
   gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(*dialog)->action_area), 5);
   gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(*dialog)->vbox), 5);
   gtk_box_set_homogeneous(GTK_BOX(GTK_DIALOG(*dialog)->action_area), TRUE);
   
   text = gtk_label_new(infotxt);
   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(*dialog)->vbox), text, TRUE, TRUE, FALSE);
   gtk_widget_show(text);

   va_start(argp, num);
   for(i=0; i<num; i++) {
      myfunc = va_arg(argp, func);
      tempstr = va_arg(argp, char *);
      ptr = va_arg(argp, void *);
      
      tempwid = gtk_button_new_with_label(tempstr);
      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(*dialog)->action_area), tempwid, TRUE, TRUE, TRUE);
      if(myfunc) {
         gtk_signal_connect(GTK_OBJECT(tempwid), "clicked", GTK_SIGNAL_FUNC(myfunc), (gpointer) ptr);
      }
      gtk_widget_show(tempwid);
   }
            
   gtk_widget_show(*dialog);
   return(*dialog);
}         
/*****************************************************************************/
