Index: src/mkshortcut/mkshortcut.c
===================================================================
RCS file: /cvs/cygwin-apps/cygutils/src/mkshortcut/mkshortcut.c,v
retrieving revision 1.10
diff -u -r1.10 mkshortcut.c
--- src/mkshortcut/mkshortcut.c	3 Dec 2009 08:19:44 -0000	1.10
+++ src/mkshortcut/mkshortcut.c	3 Jan 2010 21:02:15 -0000
@@ -1,6 +1,7 @@
 /* mkshortcut.c -- create a Windows shortcut
  *
  * Copyright (c) 2002 Joshua Daniel Franklin
+ * Copyright (c) 2010 Andy Koppe
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -28,6 +29,8 @@
  *
  */
 
+#define UNICODE
+
 #if HAVE_CONFIG_H
 # include "config.h"
 #endif
@@ -35,6 +38,9 @@
 
 #define NOCOMATTRIBUTE
 
+#include <sys/cygwin.h>
+#include <locale.h>
+#include <wchar.h>
 #include <shlobj.h>
 #include <olectlid.h>
 /* moved to common.h */
@@ -47,7 +53,10 @@
 static const char revID[] =
   "$Id: mkshortcut.c,v 1.10 2009/12/03 08:19:44 cwilson Exp $";
 static const char copyrightID[] =
-  "Copyright (c) 2002\nJoshua Daniel Franklin. All rights reserved.\nLicensed under GPL v2.0\n";
+  "Copyright (c) 2002 Joshua Daniel Franklin.\n"
+  "Copyright (c) 2010 Andy Koppe.\n"
+  "All rights reserved.\n"
+  "Licensed under GPL v2.0\n";
 
 typedef struct optvals_s
 {
@@ -67,29 +76,29 @@
   char *icon_name_arg;
 } optvals;
 
-static int mkshortcut (optvals opts, poptContext optCon);
-static void printTopDescription (FILE * f, char *name);
-static void printBottomDescription (FILE * f, char *name);
+static int mkshortcut (optvals opts);
+static void printTopDescription (void);
+static void printBottomDescription (void);
 static const char *getVersion ();
-static void usage (poptContext optCon, FILE * f, char *name);
-static void help (poptContext optCon, FILE * f, char *name);
-static void version (poptContext optCon, FILE * f, char *name);
-static void license (poptContext optCon, FILE * f, char *name);
+static void usage (void);
+static void help (void);
+static void version (void);
+static void license (void);
+static void error (char *);
+static void *nullcheck (void *);
 
 static char *program_name;
+static poptContext optCon;
 
 int
 main (int argc, const char **argv)
 {
-  poptContext optCon;
   const char **rest;
   int rc;
-  int ec = 0;
   optvals opts;
 
   const char *tmp_str;
   int icon_offset_flag;
-  char icon_name[MAX_PATH];
   const char *arg;
 
   struct poptOption helpOptionsTable[] = {
@@ -136,6 +145,8 @@
      "Help options", NULL},
     {NULL, '\0', 0, NULL, 0, NULL, NULL}
   };
+  
+  setlocale(LC_CTYPE, "");
 
   tmp_str = strrchr (argv[0], '/');
   if (tmp_str == NULL)
@@ -150,11 +161,7 @@
     {
       tmp_str++;
     }
-  if ((program_name = strdup (tmp_str)) == NULL)
-    {
-      fprintf (stderr, "%s: memory allocation error\n", argv[0]);
-      exit (2);
-    }
+  nullcheck (program_name = strdup (tmp_str));
 
   icon_offset_flag = 0;
 
@@ -181,57 +188,32 @@
       switch (rc)
         {
         case '?':
-          help (optCon, stderr, program_name);
-          goto exit;
+          help ();
+          return 0;
         case 'u':
-          usage (optCon, stderr, program_name);
-          goto exit;
+          usage ();
+          return 0;
         case 'v':
-          version (optCon, stderr, program_name);
-          goto exit;
+          version ();
+          return 0;
         case 'l':
-          license (optCon, stderr, program_name);
-          goto exit;
+          license ();
+          return 0;
         case 'd':
           if (arg = poptGetOptArg (optCon))
-            {
-              if ((opts.desc_arg = strdup (arg)) == NULL)
-                {
-                  fprintf (stderr, "%s: memory allocation error\n",
-                           program_name);
-                  ec = 2;
-                  goto exit;
-                }
-            }
+            nullcheck (opts.desc_arg = strdup (arg));
           break;
         case 'i':
           opts.icon_flag = 1;
           if (arg = poptGetOptArg (optCon))
-            {
-              cygwin_conv_to_full_win32_path (arg, icon_name);
-              if ((opts.icon_name_arg = strdup (icon_name)) == NULL)
-                {
-                  fprintf (stderr, "%s: memory allocation error\n",
-                           program_name);
-                  ec = 2;
-                  goto exit;
-                }
-            }
+            nullcheck (opts.icon_name_arg = strdup (arg));
           break;
         case 'j':
           icon_offset_flag = 1;
           break;
         case 'n':
           if (arg = poptGetOptArg (optCon))
-            {
-              if ((opts.name_arg = strdup (arg)) == NULL)
-                {
-                  fprintf (stderr, "%s: memory allocation error\n",
-                           program_name);
-                  ec = 2;
-                  goto exit;
-                }
-            }
+            nullcheck (opts.name_arg = strdup (arg));
           break;
         case 's':
           if (arg = poptGetOptArg (optCon))
@@ -252,34 +234,17 @@
                 {
                   fprintf (stderr, "%s: %s not valid for show window\n",
                            program_name, arg);
-                  ec = 2;
-                  goto exit;
+                  return 2;
                 }
             }
           break;
         case 'w':
           if (arg = poptGetOptArg (optCon))
-            {
-              if ((opts.dir_name_arg = strdup (arg)) == NULL)
-                {
-                  fprintf (stderr, "%s: memory allocation error\n",
-                           program_name);
-                  ec = 2;
-                  goto exit;
-                }
-            }
+            nullcheck (opts.dir_name_arg = strdup (arg));
           break;
         case 'a':
           if (arg = poptGetOptArg (optCon))
-            {
-              if ((opts.argument_arg = strdup (arg)) == NULL)
-                {
-                  fprintf (stderr, "%s: memory allocation error\n",
-                           program_name);
-                  ec = 2;
-                  goto exit;
-                }
-            }
+            nullcheck (opts.argument_arg = strdup (arg));
           break;
           // case 'A' 
           // case 'D'
@@ -288,44 +253,24 @@
     }
 
   if (icon_offset_flag & !opts.icon_flag)
-    {
-      fprintf (stderr,
-               "%s: --iconoffset|-j only valid in conjuction with --icon|-i\n",
-               program_name);
-      usage (optCon, stderr, program_name);
-      ec = 1;
-      goto exit;
-    }
+    error ("--iconoffset|-j only valid in conjuction with --icon|-i");
 
   if (opts.smprograms_flag && opts.desktop_flag)
-    {
-      fprintf (stderr,
-               "%s: --smprograms|-P not valid in conjuction with --desktop|-D\n",
-               program_name);
-      usage (optCon, stderr, program_name);
-      ec = 1;
-      goto exit;
-    }
+    error ("--smprograms|-P not valid in conjuction with --desktop|-D");
 
   if (rc < -1)
     {
       fprintf (stderr, "%s: bad argument %s: %s\n",
                program_name, poptBadOption (optCon, POPT_BADOPTION_NOALIAS),
                poptStrerror (rc));
-      ec = 1;
-      goto exit;
+      return 1;
     }
 
   rest = poptGetArgs (optCon);
 
   if (rest && *rest)
     {
-      if ((opts.target_arg = strdup (*rest)) == NULL)
-        {
-          fprintf (stderr, "%s: memory allocation error\n", program_name);
-          ec = 2;
-          goto exit;
-        }
+      nullcheck (opts.target_arg = strdup (*rest));
       rest++;
       if (rest && *rest)
         {
@@ -333,140 +278,118 @@
           while (*rest)
             fprintf (stderr, "%s ", *rest++);
           fprintf (stderr, "\n");
-          usage (optCon, stderr, program_name);
-          ec = 1;
+          usage ();
+          return 1;
         }
       else
         {
           // THE MEAT GOES HERE
-          ec = mkshortcut (opts, optCon);
+          return mkshortcut (opts);
         }
     }
   else
-    {
-      fprintf (stderr, "%s: TARGET not specified\n", program_name);
-      usage (optCon, stderr, program_name);
-      ec = 1;
-    }
+    error ("TARGET not specified");
+}
 
-exit:
-  poptFreeContext (optCon);
-  if (opts.target_arg)
-    {
-      free (opts.target_arg);
-    }
-  if (opts.name_arg)
-    {
-      free (opts.name_arg);
-    }
-  if (opts.desc_arg)
-    {
-      free (opts.desc_arg);
-    }
-  if (opts.dir_name_arg)
-    {
-      free (opts.dir_name_arg);
-    }
-  if (opts.argument_arg)
-    {
-      free (opts.argument_arg);
-    }
-  if (opts.icon_name_arg)
+static wchar_t *
+conv_arg (char *arg, char *arg_name)
+{
+  wchar_t *ret;
+  int len = mbstowcs(0, arg, 0);
+  if (len < 0)
+    {
+      fprintf (stderr, "%s: invalid bytes in %s\n",
+               program_name, arg_name);
+      exit (1);
+    }
+  ret = nullcheck (malloc (++len * sizeof (wchar_t)));
+  mbstowcs(ret, arg, len);
+  return ret;
+}
+
+static wchar_t *
+conv_path (char *path, cygwin_conv_path_t flags)
+{
+  wchar_t *wpath;
+
+  if (strchr (path, ':') != NULL)
+    error ("all paths must be in POSIX format");
+
+  wpath = cygwin_create_path (CCP_POSIX_TO_WIN_W | flags, path);
+  if (!wpath)
     {
-      free (opts.icon_name_arg);
+      fprintf (stderr,
+               "%s: could not convert path: $s\n",
+               program_name, path);
+      exit (1);
     }
-  free (program_name);
-  return (ec);
+
+  if (wcsncmp(wpath, L"\\\\?\\UNC\\", 8) == 0)
+    wpath += 6, *wpath = '\\'; /* Replace '\\?\UNC\' with \\ */
+  else if (wcsncmp(wpath, L"\\\\?\\", 4) == 0)
+    wpath += 4; /* Drop '\\?\' */
+  
+  return wpath;
 }
 
 int
-mkshortcut (optvals opts, poptContext optCon)
+mkshortcut (optvals opts)
 {
-  char link_name[MAX_PATH];
-  char exe_name[MAX_PATH];
-  char dir_name[MAX_PATH];
-  char desc[MAX_PATH];
-  char *buf_str, *tmp_str;
-  int tmp;
+  wchar_t *link_name, *link_base;
+  wchar_t *exe_name;
+  wchar_t *dir_name;
+  wchar_t *icon_name;
+  wchar_t *desc;
+  wchar_t *args;
+  int len;
 
   /* For OLE interface */
-  LPITEMIDLIST id;
   HRESULT hres;
   IShellLink *shell_link;
   IPersistFile *persist_file;
-  WCHAR widepath[MAX_PATH];
-
-  buf_str = (char *) malloc (PATH_MAX);
-  if (buf_str == NULL)
-    {
-      fprintf (stderr, "%s: out of memory\n", program_name);
-      return (2);
-    }
 
   /*  If there's a colon in the TARGET, it should be a URL */
   if (strchr (opts.target_arg, ':') != NULL)
     {
       /*  Nope, somebody's trying a W32 path  */
       if (opts.target_arg[1] == ':')
-        {
-          free (buf_str);
-          fprintf (stderr, "%s: all paths must be in POSIX format\n",
-                   program_name);
-          usage (optCon, stderr, program_name);
-          return (1);
-        }
-      strcpy (exe_name, opts.target_arg);
-      dir_name[0] = '\0';       /* No working dir for URL */
+        error ("all paths must be in POSIX format");
+        
+      exe_name = conv_arg (opts.target_arg, "target URL");
+      dir_name = L"";       /* No working dir for URL */
     }
   /* Convert TARGET to win32 path */
   else
     {
-      strcpy (buf_str, opts.target_arg);
-      cygwin_conv_to_full_win32_path (buf_str, exe_name);
+      exe_name = conv_path (opts.target_arg, 0);
 
       /*  Get a working dir from 'w' option */
       if (opts.dir_name_arg != NULL)
-        {
-          if (strchr (opts.dir_name_arg, ':') != NULL)
-            {
-              free (buf_str);
-              fprintf (stderr, "%s: all paths must be in POSIX format\n",
-                       program_name);
-              usage (optCon, stderr, program_name);
-              return (1);
-            }
-          cygwin_conv_to_win32_path (opts.dir_name_arg, dir_name);
-        }
+        dir_name = conv_path (opts.dir_name_arg, 0);
       /*  Get a working dir from the exepath */
       else
         {
-          tmp_str = strrchr (exe_name, '\\');
-          tmp = strlen (exe_name) - strlen (tmp_str);
-          strncpy (dir_name, exe_name, tmp);
-          dir_name[tmp] = '\0';
+          wchar_t *last_slash = wcsrchr (exe_name, '\\');
+          if (last_slash) {
+            len = last_slash - exe_name;
+            dir_name = nullcheck (malloc ((len + 1) * sizeof(wchar_t)));
+            wmemcpy (dir_name, exe_name, len);
+            dir_name[len] = 0;
+          }
+          else
+            dir_name = L"";
         }
     }
 
   /*  Generate a name for the link if not given */
   if (opts.name_arg == NULL)
     {
-      /*  Strip trailing /'s if any */
-      strcpy (buf_str, opts.target_arg);
-      tmp_str = buf_str;
-      tmp = strlen (buf_str) - 1;
-      while (strrchr (buf_str, '/') == (buf_str + tmp))
-        {
-          buf_str[tmp] = '\0';
-          tmp--;
-        }
-      /*  Get basename */
-      while (*buf_str)
-        {
-          if (*buf_str == '/')
-            tmp_str = buf_str + 1;
-          buf_str++;
-        }
-      strcpy (link_name, tmp_str);
+      wchar_t *last_slash = wcsrchr (exe_name, '\\');
+      if (!last_slash)
+        last_slash = wcsrchr (exe_name, '/');
+      if (!last_slash)
+        error("need link name");
+      link_base = last_slash + 1;
     }
   /*  User specified a name, so check it and convert  */
   else
@@ -475,93 +398,66 @@
         {
           /*  Cannot have absolute path relative to Desktop/SM Programs */
           if (opts.name_arg[0] == '/')
-            {
-              free (buf_str);
-              fprintf (stderr,
-                       "%s: absolute pathnames not allowed with -D/-P\n",
-                       program_name);
-              usage (optCon, stderr, program_name);
-              return (1);
-            }
-        }
-      /*  Sigh. Another W32 path */
-      if (strchr (opts.name_arg, ':') != NULL)
-        {
-          free (buf_str);
-          fprintf (stderr, "%s: all paths must be in POSIX format\n",
-                   program_name);
-          usage (optCon, stderr, program_name);
-          return (1);
+            error ("absolute pathnames not allowed with -D/-P");
         }
-      cygwin_conv_to_win32_path (opts.name_arg, link_name);
+      
+      link_base = conv_path (opts.name_arg, CCP_RELATIVE);
     }
-
-  /*  Add suffix to link name if necessary */
-  if (strlen (link_name) > 4)
-    {
-      tmp = strlen (link_name) - 4;
-      if (strncmp (link_name + tmp, ".lnk", 4) != 0)
-        strcat (link_name, ".lnk");
-    }
-  else
-    strcat (link_name, ".lnk");
-
-  /*  Prepend relative path if necessary  */
-  if (opts.desktop_flag)
-    {
-      strcpy (buf_str, link_name);
-      if (!opts.allusers_flag)
-        SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
+  
+  /* Make space for the full link path */
+  len = wcslen (link_base);
+  link_name = nullcheck (malloc((MAX_PATH + len + 8) * sizeof (wchar_t)));
+
+  /* Get special folder location if required */
+  if (opts.desktop_flag || opts.smprograms_flag)
+    {
+      int dir;
+      LPITEMIDLIST id;
+      if (opts.desktop_flag)
+        dir = opts.allusers_flag ? CSIDL_COMMON_DESKTOPDIRECTORY
+                                 : CSIDL_DESKTOPDIRECTORY;
       else
-        SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_DESKTOPDIRECTORY, &id);
+        dir = opts.allusers_flag ? CSIDL_COMMON_PROGRAMS
+                                 : CSIDL_PROGRAMS;      
+      SHGetSpecialFolderLocation (NULL, dir, &id);
       SHGetPathFromIDList (id, link_name);
-      /*  Make sure Win95 without "All Users" has output  */
-      if (strlen (link_name) == 0)
-        {
-          SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
-          SHGetPathFromIDList (id, link_name);
-        }
-      strcat (link_name, "\\");
-      strcat (link_name, buf_str);
+      wcscat (link_name, L"\\");
     }
-
-  if (opts.smprograms_flag)
-    {
-      strcpy (buf_str, link_name);
-      if (!opts.allusers_flag)
-        SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
-      else
-        SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_PROGRAMS, &id);
-      SHGetPathFromIDList (id, link_name);
-      /*  Make sure Win95 without "All Users" has output  */
-      if (strlen (link_name) == 0)
-        {
-          SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
-          SHGetPathFromIDList (id, link_name);
-        }
-      strcat (link_name, "\\");
-      strcat (link_name, buf_str);
-    }
-
-  /* Setup description text */
+  else
+    *link_name = 0;
+  
+  wcscat(link_name, link_base);
+
+  /* Append ".lnk" if necessary. */
+  if (len <= 4 || wcscmp (link_base + len - 4, L".lnk") != 0)
+    wcscat(link_name, L".lnk");
+  
+  /* Convert icon name */
+  if (opts.icon_name_arg != NULL)
+    icon_name = conv_path (opts.icon_name_arg, 0);
+  else
+    icon_name = NULL;
+  
+  /* Convert shortcut argument */
+  if (opts.argument_arg != NULL)
+    args = conv_arg (opts.argument_arg, "argument");
+  else
+    args = NULL;
+  
+  /* Convert description */
   if (opts.desc_arg != NULL)
-    {
-      strncpy (desc, opts.desc_arg, MAX_PATH);
-
-      /* There won't be a null terminated if strlen(desc_arg)>MAX_PATH */
-      desc[MAX_PATH - 1] = '\0';
-    }
+    desc = conv_arg (opts.desc_arg, "description");
   else
     {
       /* Put the POSIX path in the "Description", just to be nice */
-      cygwin_conv_to_full_posix_path (exe_name, desc);
+      desc = conv_arg(cygwin_create_path(CCP_WIN_W_TO_POSIX, exe_name),
+                      "executable name");
     }
 
   /*  Beginning of Windows interface */
   hres = OleInitialize (NULL);
   if (hres != S_FALSE && hres != S_OK)
     {
-      free (buf_str);
       fprintf (stderr, "%s: Could not initialize OLE interface\n",
                program_name);
       return (3);
@@ -581,32 +477,19 @@
           shell_link->lpVtbl->SetDescription (shell_link, desc);
           shell_link->lpVtbl->SetWorkingDirectory (shell_link, dir_name);
           if (opts.argument_arg)
-            shell_link->lpVtbl->SetArguments (shell_link, opts.argument_arg);
+            shell_link->lpVtbl->SetArguments (shell_link, args);
           if (opts.icon_flag)
             shell_link->lpVtbl->SetIconLocation (shell_link,
-                                                 opts.icon_name_arg,
+                                                 icon_name,
                                                  opts.offset);
           if (opts.show_flag != SW_SHOWNORMAL)
             shell_link->lpVtbl->SetShowCmd (shell_link, opts.show_flag);
 
-
-          /*  Make link name Unicode-compliant  */
-          hres =
-            MultiByteToWideChar (CP_ACP, 0, link_name, -1, widepath,
-                                 MAX_PATH);
+          hres = persist_file->lpVtbl->Save (persist_file, link_name, TRUE);
           if (!SUCCEEDED (hres))
             {
-              free (buf_str);
-              fprintf (stderr, "%s: Unicode translation failed%d\n",
-                       program_name, hres);
-              return (3);
-            }
-          hres = persist_file->lpVtbl->Save (persist_file, widepath, TRUE);
-          if (!SUCCEEDED (hres))
-            {
-              free (buf_str);
               fprintf (stderr,
-                       "%s: Saving \"%s\" failed; does the target directory exist?\n",
+                       "%s: Saving \"%ls\" failed\n",
                        program_name, link_name);
               return (3);
             }
@@ -615,17 +498,17 @@
         }
       else
         {
-          free (buf_str);
           fprintf (stderr, "%s: QueryInterface failed\n", program_name);
           return (3);
         }
     }
   else
     {
-      free (buf_str);
       fprintf (stderr, "%s: CoCreateInstance failed\n", program_name);
       return (3);
     }
+  
+  return 0;
 }
 
 static const char *
@@ -635,71 +518,91 @@
 }
 
 static void
-printTopDescription (FILE * f, char *name)
+printTopDescription (void)
 {
-  char s[20];
-  fprintf (f, "%s is part of cygutils version %s\n", name, getVersion ());
-  fprintf (f, "  create a Windows shortcut\n\n");
+  fprintf (stderr, "%s is part of cygutils version %s\n",
+                   program_name, getVersion ());
+  fprintf (stderr, "  create a Windows shortcut\n\n");
 }
 static void
-printBottomDescription (FILE * f, char *name)
+printBottomDescription (void)
 {
-  fprintf (f,
+  fprintf (stderr,
            "\nNOTE: All filename arguments must be in unix (POSIX) format\n");
 }
 
 static
-printLicense (FILE * f, char *name)
+printLicense (void)
 {
-  fprintf (f,
+  fprintf (stderr,
            "This program is free software; you can redistribute it and/or\n");
-  fprintf (f,
+  fprintf (stderr,
            "modify it under the terms of the GNU General Public License\n");
-  fprintf (f,
+  fprintf (stderr,
            "as published by the Free Software Foundation; either version 2\n");
-  fprintf (f, "of the License, or (at your option) any later version.\n");
-  fprintf (f, "\n");
-  fprintf (f,
+  fprintf (stderr, "of the License, or (at your option) any later version.\n");
+  fprintf (stderr, "\n");
+  fprintf (stderr,
            "This program is distributed in the hope that it will be useful,\n");
-  fprintf (f,
+  fprintf (stderr,
            "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
-  fprintf (f,
+  fprintf (stderr,
            "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
-  fprintf (f, "GNU General Public License for more details.\n");
-  fprintf (f, "\n");
-  fprintf (f,
+  fprintf (stderr, "GNU General Public License for more details.\n");
+  fprintf (stderr, "\n");
+  fprintf (stderr,
            "You should have received a copy of the GNU General Public License\n");
-  fprintf (f,
+  fprintf (stderr,
            "along with this program; if not, write to the Free Software\n");
-  fprintf (f,
+  fprintf (stderr,
            "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n");
-  fprintf (f, "\n");
-  fprintf (f, "See the COPYING file for license information.\n");
+  fprintf (stderr, "\n");
+  fprintf (stderr, "See the COPYING file for license information.\n");
 }
+
+static void
+usage (void)
+{
+  poptPrintUsage (optCon, stderr, 0);
+}
+
 static void
-usage (poptContext optCon, FILE * f, char *name)
+help (void)
 {
-  poptPrintUsage (optCon, f, 0);
+  printTopDescription ();
+  poptPrintHelp (optCon, stderr, 0);
+  printBottomDescription ();
 }
 
 static void
-help (poptContext optCon, FILE * f, char *name)
+version (void)
 {
-  printTopDescription (f, name);
-  poptPrintHelp (optCon, f, 0);
-  printBottomDescription (f, name);
+  printTopDescription ();
+  fprintf (stderr, copyrightID);
 }
 
 static void
-version (poptContext optCon, FILE * f, char *name)
+license (void)
 {
-  printTopDescription (f, name);
-  fprintf (f, copyrightID);
+  printTopDescription ();
+  printLicense ();
 }
 
 static void
-license (poptContext optCon, FILE * f, char *name)
+error (char *msg)
 {
-  printTopDescription (f, name);
-  printLicense (f, name);
+  fprintf (stderr, "%s: %s\n", program_name, msg);
+  usage ();
+  exit (1);
+}
+
+static void *
+nullcheck (void *p)
+{
+  if (p == NULL)
+    {
+      fprintf (stderr, "%s: memory allocation error\n", program_name);
+      exit (2);
+    }
+  return p;
 }
