gpgscm: Add types for special objects.
[gnupg.git] / doc / mkdefsinc.c
1 /* mkdefsinc.c - Tool to create defs.inc
2  * Copyright (C) 2015 g10 Code GmbH
3  *
4  * This file is free software; as a special exception the author gives
5  * unlimited permission to copy and/or distribute it, with or without
6  * modifications, as long as this notice is preserved.
7  *
8  * This file is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
10  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  */
12
13 /* This tool needs to be build with command line supplied -D options
14    for the various directory variables.  See ../am/cmacros.am.  It is
15    easier to do this in build file than to use fragile make rules and
16    a template file.  */
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <time.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27
28 #define PGM "mkdefsinc"
29
30 /* We include config.h after all include files because the config.h
31    values are not valid for the build platform but we need some values
32    nevertheless.  */
33 #include "config.h"
34 /* When building for Windows the -D macros do not have appropriate
35    values.  We provide replacements here.  */
36 #ifdef HAVE_W32_SYSTEM
37 # undef  GNUPG_BINDIR
38 # undef  GNUPG_LIBEXECDIR
39 # undef  GNUPG_LIBDIR
40 # undef  GNUPG_DATADIR
41 # undef  GNUPG_SYSCONFDIR
42 # undef  GNUPG_LOCALSTATEDIR
43 # define GNUPG_BINDIR        "INSTDIR/bin"
44 # define GNUPG_LIBEXECDIR    "INSTDIR/bin"
45 # define GNUPG_LIBDIR        "INSTDIR/lib/" PACKAGE_NAME
46 # define GNUPG_DATADIR       "INSTDIR/share/" PACKAGE_NAME
47 # define GNUPG_SYSCONFDIR    "APPDATA/GNU/etc/" PACKAGE_NAME
48 # define GNUPG_LOCALSTATEDIR "APPDATA/GNU"
49 #endif /*HAVE_W32_SYSTEM*/
50
51
52 #if USE_GPG2_HACK
53 # define gpg2_suffix "2"
54 #else
55 # define gpg2_suffix ""
56 #endif
57
58
59 static int verbose;
60
61
62 /* The usual free wrapper.  */
63 static void
64 xfree (void *a)
65 {
66   if (a)
67     free (a);
68 }
69
70
71 static char *
72 xmalloc (size_t n)
73 {
74   char *p;
75
76   p = malloc (n);
77   if (!p)
78     {
79       fputs (PGM ": out of core\n", stderr);
80       exit (1);
81     }
82   return p;
83 }
84
85
86 static char *
87 xstrdup (const char *string)
88 {
89   char *p;
90
91   p = xmalloc (strlen (string)+1);
92   strcpy (p, string);
93   return p;
94 }
95
96
97 /* Return a malloced string with the last modification date of the
98    FILES.  Returns NULL on error.  */
99 static char *
100 get_date_from_files (char **files)
101 {
102   const char *file;
103   const char *usedfile = NULL;
104   struct stat sb;
105   struct tm *tp;
106   int errors = 0;
107   time_t stamp = 0;
108   char *result;
109
110   for (; (file = *files); files++)
111     {
112       if (!*file || !strcmp (file, ".") || !strcmp (file, ".."))
113         continue;
114       if (stat (file, &sb))
115         {
116           fprintf (stderr, PGM ": stat failed for '%s': %s\n",
117                    file, strerror (errno));
118           errors = 1;
119           continue;
120         }
121       if (sb.st_mtime > stamp)
122         {
123           stamp = sb.st_mtime;
124           usedfile = file;
125         }
126     }
127   if (errors)
128     exit (1);
129
130   if (usedfile)
131     fprintf (stderr, PGM ": taking date from '%s'\n", usedfile);
132
133   tp = gmtime (&stamp);
134   if (!tp)
135     return NULL;
136   result = xmalloc (4+1+2+1+2+1);
137   snprintf (result, 4+1+2+1+2+1, "%04d-%02d-%02d",
138             tp->tm_year + 1900, tp->tm_mon+1, tp->tm_mday);
139   return result;
140 }
141
142
143
144 int
145 main (int argc, char **argv)
146 {
147   int last_argc = -1;
148   char *opt_date = NULL;
149   int monthoff;
150   char *p, *pend;
151   size_t n;
152
153   /* Option parsing.  */
154   if (argc)
155     {
156       argc--; argv++;
157     }
158   while (argc && last_argc != argc )
159     {
160       last_argc = argc;
161       if (!strcmp (*argv, "--"))
162         {
163           argc--; argv++;
164           break;
165         }
166       else if (!strcmp (*argv, "--help"))
167         {
168           fputs ("Usage: " PGM " [OPTION] [FILES]\n"
169                  "Create defs.inc file.\nOptions:\n"
170                  "  -C DIR         Change to DIR before doing anything\n"
171                  "  --date STRING  Take publication date from STRING\n"
172                  "  --verbose      Enable extra informational output\n"
173                  "  --help         Display this help and exit\n"
174                  , stdout);
175           exit (0);
176         }
177       else if (!strcmp (*argv, "--verbose"))
178         {
179           verbose = 1;
180           argc--; argv++;
181         }
182       else if (!strcmp (*argv, "-C"))
183         {
184           argc--; argv++;
185           if (argc)
186             {
187               if (chdir (*argv))
188                 {
189                   fprintf (stderr, PGM ": chdir to '%s' failed: %s\n",
190                            *argv, strerror (errno));
191                   exit (1);
192                 }
193               argc--; argv++;
194             }
195         }
196       else if (!strcmp (*argv, "--date"))
197         {
198           argc--; argv++;
199           if (argc)
200             {
201               opt_date = xstrdup (*argv);
202               argc--; argv++;
203             }
204         }
205       else if (!strncmp (*argv, "--", 2))
206         {
207           fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
208           exit (1);
209         }
210     }
211
212   if (opt_date && *opt_date)
213     {
214       time_t stamp;
215       struct tm *tp;
216
217       if (*opt_date == '2' && strlen (opt_date) >= 10
218           && opt_date[4] == '-' && opt_date[7] == '-')
219         {
220           opt_date[10] = 0;
221         }
222       else if ((stamp = strtoul (opt_date, NULL, 10)) > 0
223                && (tp = gmtime (&stamp)))
224         {
225           p = xmalloc (4+1+2+1+2+1);
226           snprintf (p, 4+1+2+1+2+1, "%04d-%02d-%02d",
227                     tp->tm_year + 1900, tp->tm_mon+1, tp->tm_mday);
228           xfree (opt_date);
229           opt_date = p;
230         }
231       else
232         {
233           fprintf (stderr, PGM ": bad date '%s'\n", opt_date);
234           exit (1);
235         }
236     }
237   else
238     {
239       xfree (opt_date);
240       opt_date = argc? get_date_from_files (argv) : NULL;
241     }
242   if (!opt_date)
243     {
244       opt_date = xstrdup ("unknown");
245       monthoff = 0;
246     }
247   else
248     {
249       const char *month = "?";
250
251       switch (atoi (opt_date+5))
252         {
253         case  1: month = "January"; break;
254         case  2: month = "February"; break;
255         case  3: month = "March"; break;
256         case  4: month = "April"; break;
257         case  5: month = "May"; break;
258         case  6: month = "June"; break;
259         case  7: month = "July"; break;
260         case  8: month = "August"; break;
261         case  9: month = "September"; break;
262         case 10: month = "October"; break;
263         case 11: month = "November"; break;
264         case 12: month = "December"; break;
265         }
266       n = strlen (opt_date) + strlen (month) + 2 + 1;
267       p = xmalloc (n);
268       snprintf (p, n, "%d %n%s %d",
269                 atoi (opt_date+8), &monthoff, month, atoi (opt_date));
270       xfree (opt_date);
271       opt_date = p;
272     }
273
274
275   fputs ("@c defs.inc                         -*- texinfo -*-\n"
276          "@c Common and build specific constants for the manuals.\n"
277          "@c This file has been created by " PGM ".\n\n", stdout);
278
279   fputs ("@ifclear defsincincluded\n"
280          "@set defsincincluded 1\n\n", stdout);
281
282
283   fputs ("\n@c Flags\n\n", stdout);
284
285 #if USE_GPG2_HACK
286   fputs ("@set gpgtwohack 1\n\n", stdout);
287 #endif
288
289   fputs ("\n@c Directories\n\n", stdout);
290
291   fputs ("@set BINDIR         " GNUPG_BINDIR        "\n"
292          "@set LIBEXECDIR     " GNUPG_LIBEXECDIR    "\n"
293          "@set LIBDIR         " GNUPG_LIBDIR        "\n"
294          "@set DATADIR        " GNUPG_DATADIR       "\n"
295          "@set SYSCONFDIR     " GNUPG_SYSCONFDIR    "\n"
296          "@set LOCALSTATEDIR  " GNUPG_LOCALSTATEDIR "\n"
297          "@set LOCALCACHEDIR  " GNUPG_LOCALSTATEDIR
298          /*                  */ "/cache/" PACKAGE_NAME "\n"
299          "@set LOCALRUNDIR    " GNUPG_LOCALSTATEDIR
300          /*                  */ "/run/"  PACKAGE_NAME "\n"
301          , stdout);
302
303   p = xstrdup (GNUPG_SYSCONFDIR);
304   pend = strrchr (p, '/');
305   fputs ("@set SYSCONFSKELDIR ", stdout);
306   if (pend)
307     {
308       *pend = 0;
309       fputs (p, stdout);
310     }
311   fputs ("/skel/." PACKAGE_NAME "\n", stdout);
312   xfree (p);
313
314   fputs ("\n@c Version information a la version.texi\n\n", stdout);
315
316   printf ("@set UPDATED %s\n", opt_date);
317   printf ("@set UPDATED-MONTH %s\n", opt_date + monthoff);
318   printf ("@set EDITION %s\n", PACKAGE_VERSION);
319   printf ("@set VERSION %s\n", PACKAGE_VERSION);
320
321   fputs ("\n@c Algorithm defaults\n\n", stdout);
322
323   /* Fixme: Use a config.h macro here:  */
324   fputs ("@set GPGSYMENCALGO AES-128\n", stdout);
325
326   fputs ("\n@c Macros\n\n", stdout);
327
328   printf ("@macro gpgname\n%s%s\n@end macro\n", GPG_NAME, gpg2_suffix);
329   printf ("@macro gpgvname\n%sv%s\n@end macro\n", GPG_NAME, gpg2_suffix);
330
331
332   /* Trailer.  */
333   fputs ("\n"
334          "@end ifclear\n"
335          "\n"
336          "@c Loc" "al Variables:\n"
337          "@c buffer-read-only: t\n"
338          "@c End:\n", stdout);
339
340   if (ferror (stdout))
341     {
342       fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno));
343       return 1;
344     }
345
346   return 0;
347 }