~ubuntu-branches/ubuntu/lucid/dpkg/lucid

« back to all changes in this revision

Viewing changes to lib/dpkg/myopt.c

  • Committer: Bazaar Package Importer
  • Author(s): Guillem Jover, Guillem Jover, Raphael Hertzog, Modestas Vainius, Updated dpkg translations, Updated dselect translations, Updated man page translations, Updated scripts translations
  • Date: 2009-09-06 09:37:45 UTC
  • mto: (1.4.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 68.
  • Revision ID: james.westby@ubuntu.com-20090906093745-orb3im04ozfxypis
Tags: 1.15.4
[ Guillem Jover ]
* Call _g instead of g_ in dpkg-name.
* Fix inverted logic when deciding to assume the architecture in dpkg-name
  when the package didn't have such field.
* Do not take into account Revision and Package_Revision fields in dpkg-name
  and dpkg-scanpackages as they have been handled already by “dpkg-deb -I”.
* Switch dpkg-scansources to use Dpkg::Cdata instead of duplicating the
  .dsc parsing code. As a side effect it now handles properly bogus files.
* Do not remap obsolete fields in dpkg-scanpackages as they have been
  handled already by “dpkg-deb -I”.
* Properly mark packages being purged for disappearance from the database.
  This will make the status database not be left behind with traces of old
  not-installed packages. Closes: #472208
* On parse mark not-installed leftover packages for automatic removal from
  the database on next dump. This obsoletes the --forget-old-unavail option,
  thus making it now a no-op. Closes: #33394, #429262
* Document “hold” under package selection states instead of flags in dpkg(1).
* Remove trailing ‘/’ and ‘/.’ from the directory name to be used as the
  package name on “dpkg-deb -b”. Closes: #218018, #373602
* Remove obsolete ‘hold’ and ‘hold-reinstreq’ internal status flags.
* Add fakeroot to dpkg-dev Recommends. Closes: #536821
* Fix an always false test when trying to decide which package to deselect
  to resolve a dependency problem in dselect.
* Add uClibc Linux support to ostable and triplettable. Closes: #455501
* Add uClinux support to ostable and triplettable.
  Thanks to Simon Richter <sjr@debian.org>.
* When aborting due to file conflicts print the version of the conflicted
  package. Closes: #540019
* Remove double slash in database path visible to the user in some error
  conditions.
* Stop macthing sparc64-*-* GNU triplets with sparc Debian architecture.
* Add support for config.d style directories in dpkg and dselect,
  (/etc/dpkg/dpkg.cfg.d and /etc/dpkg/dselect.cfg.d respectively).
* Define DPKG_MAINTSCRIPT_ARCH on the maintainer script environment to the
  architecture the package got built for.
* Document DPKG_MAINTSCRIPT_PACKAGE maintainer script environment variable
  in dpkg man page.
* Document DPKG_RUNNING_VERSION maintainer script environment variable
  in dpkg man page.
* Change po4a usage to not create unwated changes depending if doing out or
  in-tree builds.
* Use po4a “--previous” support when updating the man pages.
  Suggested by Christian Perrier <bubulle@debian.org>.
* On configuration error print file name and line number.
* Allow quoting values in configuration file options.
* Add new --pre-invoke and --post-invoke hooks in dpkg.
* Add new --control-path command to dpkg-query.
* Use ohshit on bad version syntax in --compare-versions.
* Add Multi-Arch to the list of known binary package fields for dpkg-dev.
  Thanks to Steve Langasek <vorlon@debian.org>.

[ Raphael Hertzog ]
* Replace install-info by a wrapper around GNU's install-info. The wrapper
  will be dropped in squeeze+1. dpkg now Breaks: old versions of
  info-browsers that do not depend on the new install-info package
  that provides the real functionality. Closes: #9771, #523980
  See http://wiki.debian.org/Transitions/DpkgToGnuInstallInfo for details.
* Fix dpkg's preinst in case /var/lib/dpkg/alternatives contains unexpected
  sub-directories. Closes: #535138
  And also when one of the file doesn't contain correct alternatives
  information (improper number of lines). Closes: #537558
* Upgrade Standards-Version to 3.8.2 (no changes).
* Update deb-substvars(5) to list fields that do not support substvars.
  Closes: #535353
* Fix dpkg-parsechangelog to include all entries with -v0 parameter.
  Closes: #537800
* Fix update-alternatives to mention the correct slave link that can't
  be installed due to a conflicting file instead of quoting the master link.
* Add support for extra override file in dpkg-scanpackages. Thanks to Robert
  Millan for the patch. Closes: #537559
* Add support for extra override file in dpkg-scansources.
* Document format of extra override file in a new manual page
  deb-extra-override(5).
* Update sample in dpkg-gensymbols(1) to give an accurate listing of
  64 bit arches. Thanks to Julien Cristau for the patch. Closes: #540382
* Create /etc/cron.daily/dpkg to handle the backup of
  /var/lib/dpkg/status in /var/backups. This is taken out of the cron
  package and need no conflicts/breaks as the code does nothing if
  the current status file is already backupped. Thanks to Leo 'costela'
  Antunes <costela@debian.org> for the patch. Closes: #541412
* Change behaviour of dpkg --merge-avail to not update a package's
  information if the version provided is older than the one already listed
  in the available file. Thanks to Ian Jackson
  <ian@davenant.greenend.org.uk> for the patch. Closes: #496114
* dpkg-architecture can now export DEB_{HOST,BUILD}_ARCH_{BITS,ENDIAN}
  (pointer size and endianness):
  - cputable (in dpkg) modified to contain those information
  - dpkg-dev depends on dpkg (>= 1.15.4) to ensure that we have an updated
    cputable (and so that a versioned build-dependency on dpkg-dev is enough
    to use this new feature)
  Closes: #531307
* Split overly long Binary: field values over multiple lines. This is
  allowed since policy 3.8.3. Closes: #494714
* Improve performance of dpkg-shlibdeps by caching minimal version
  associated to each library in Dpkg::Shlib::SymbolFile. Thanks to
  Jiří Paleček <jpalecek@web.de> for the patch.
* Slightly improve dpkg-source(1) by giving the section name that we're
  referring to. Closes: #544037
* Fix translation error in german manpage of dpkg-buildpackage. Thanks
  to Joachim Breitner <nomeata@debian.org>. Closes: #541829

[ Modestas Vainius ]
* Provide a meaningful label for dpkg-gensymbols diff.

[ Updated dpkg translations ]
* Asturian (Marcos Alvarez Costales). Closes: #535327
* French (Christian Perrier).
* German (Sven Joachim).
* Italian (Milo Casagrande). Closes: #536538
* Russian (Yuri Kozlov). Closes: #542254
* Slovak (Ivan Masár). Closes: #537742
* Swedish (Peter Krefting).

[ Updated dselect translations ]
* Russian (Yuri Kozlov). Closes: #542254
* Slovak (Ivan Masár). Closes: #537741

[ Updated man page translations ]
* French (Christian Perrier).
* German (Helge Kreutzmann), proofread by Jens Seidel.
* Swedish (Peter Krefting).

[ Updated scripts translations ]
* French completed (Christian Perrier).
* German (Helge Kreutzmann).
* Russian (Yuri Kozlov). Closes: #542254
* Swedish (Peter Krefting).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libdpkg - Debian packaging suite library routines
 
3
 * myopt.c - my very own option parsing
 
4
 *
 
5
 * Copyright © 1994,1995 Ian Jackson <ian@chiark.greenend.org.uk>
 
6
 * Copyright © 2000,2002 Wichert Akkerman <wichert@deephackmode.org>
 
7
 * Copyright © 2008,2009 Guillem Jover <guillem@debian.org>
 
8
 *
 
9
 * This is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as
 
11
 * published by the Free Software Foundation; either version 2,
 
12
 * or (at your option) any later version.
 
13
 *
 
14
 * This is distributed in the hope that it will be useful, but
 
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public
 
20
 * License along with this file; if not, write to the Free Software
 
21
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
22
 */
 
23
#include <config.h>
 
24
#include <compat.h>
 
25
 
 
26
#include <dpkg/i18n.h>
 
27
 
 
28
#include <string.h>
 
29
#include <errno.h>
 
30
#include <ctype.h>
 
31
#include <dirent.h>
 
32
#include <stdarg.h>
 
33
#include <stdlib.h>
 
34
 
 
35
#include <dpkg/dpkg.h>
 
36
#include <dpkg/string.h>
 
37
#include <dpkg/myopt.h>
 
38
 
 
39
void
 
40
badusage(const char *fmt, ...)
 
41
{
 
42
  char buf[1024];
 
43
  va_list al;
 
44
 
 
45
  va_start(al, fmt);
 
46
  vsnprintf(buf, sizeof(buf), fmt, al);
 
47
  va_end(al);
 
48
 
 
49
  ohshit("%s\n\n%s", buf, gettext(printforhelp));
 
50
}
 
51
 
 
52
static void
 
53
config_error(const char *file_name, int line_num, const char *fmt, ...)
 
54
{
 
55
  char buf[1024];
 
56
  va_list al;
 
57
 
 
58
  va_start(al, fmt);
 
59
  vsnprintf(buf, sizeof(buf), fmt, al);
 
60
  va_end(al);
 
61
 
 
62
  ohshit(_("configuration error: %s:%d: %s"), file_name, line_num, buf);
 
63
}
 
64
 
 
65
void myfileopt(const char* fn, const struct cmdinfo* cmdinfos) {
 
66
  FILE* file;
 
67
  int line_num = 0;
 
68
  char linebuf[MAX_CONFIG_LINE];
 
69
 
 
70
  file= fopen(fn, "r");
 
71
  if (!file) {
 
72
    if (errno==ENOENT)
 
73
      return;
 
74
    warning(_("failed to open configuration file '%.255s' for reading: %s"),
 
75
            fn, strerror(errno));
 
76
    return;
 
77
  }
 
78
 
 
79
  while (fgets(linebuf, sizeof(linebuf), file)) {
 
80
    char* opt;
 
81
    const struct cmdinfo *cip;
 
82
    int l;
 
83
 
 
84
    line_num++;
 
85
 
 
86
    if ((linebuf[0] == '#') || (linebuf[0] == '\n') || (linebuf[0] == '\0'))
 
87
      continue;
 
88
    l=strlen(linebuf);
 
89
    if (linebuf[l - 1] == '\n')
 
90
      linebuf[l - 1] = '\0';
 
91
    for (opt=linebuf;isalnum(*opt)||*opt=='-';opt++) ;
 
92
    if (*opt == '\0')
 
93
      opt=NULL;
 
94
    else {
 
95
      *opt++ = '\0';
 
96
      if (*opt=='=') opt++;
 
97
      while (isspace(*opt)) opt++;
 
98
 
 
99
      opt = str_strip_quotes(opt);
 
100
      if (opt == NULL)
 
101
        config_error(fn, line_num, _("unbalanced quotes in '%s'"), linebuf);
 
102
    }
 
103
 
 
104
    for (cip=cmdinfos; cip->olong || cip->oshort; cip++) {
 
105
      int l;
 
106
      if (!cip->olong) continue;
 
107
      if (!strcmp(cip->olong,linebuf)) break;
 
108
      l=strlen(cip->olong);
 
109
      if ((cip->takesvalue==2) && (linebuf[l]=='-') &&
 
110
          !opt && !strncmp(linebuf,cip->olong,l)) {
 
111
        opt=linebuf+l+1;
 
112
        break;
 
113
      }
 
114
    }
 
115
 
 
116
    if (!cip->olong)
 
117
      config_error(fn, line_num, _("unknown option '%s'"), linebuf);
 
118
 
 
119
    if (cip->takesvalue) {
 
120
      if (!opt)
 
121
        config_error(fn, line_num, _("'%s' needs a value"), linebuf);
 
122
      if (cip->call) cip->call(cip,opt);
 
123
      else
 
124
        *cip->sassignto = m_strdup(opt);
 
125
    } else {
 
126
      if (opt)
 
127
        config_error(fn, line_num, _("'%s' does not take a value"), linebuf);
 
128
      if (cip->call) cip->call(cip,NULL);
 
129
      else *cip->iassignto= cip->arg;
 
130
    }
 
131
  }
 
132
  if (ferror(file)) ohshite(_("read error in configuration file `%.255s'"), fn);
 
133
  if (fclose(file)) ohshite(_("error closing configuration file `%.255s'"), fn);
 
134
}
 
135
 
 
136
static int
 
137
valid_config_filename(const struct dirent *dent)
 
138
{
 
139
  const char *c;
 
140
 
 
141
  if (dent->d_name[0] == '.')
 
142
    return 0;
 
143
 
 
144
  for (c = dent->d_name; *c; c++)
 
145
    if (!isalnum(*c) && *c != '_' && *c != '-')
 
146
      return 0;
 
147
 
 
148
  if (*c == '\0')
 
149
    return 1;
 
150
  else
 
151
    return 0;
 
152
}
 
153
 
 
154
static void
 
155
load_config_dir(const char *prog, const struct cmdinfo* cmdinfos)
 
156
{
 
157
  char *dirname;
 
158
  struct dirent **dlist;
 
159
  int dlist_n, i;
 
160
 
 
161
  dirname = m_malloc(strlen(CONFIGDIR "/.cfg.d") + strlen(prog) + 1);
 
162
  sprintf(dirname, "%s/%s.cfg.d", CONFIGDIR, prog);
 
163
 
 
164
  dlist_n = scandir(dirname, &dlist, valid_config_filename, alphasort);
 
165
  if (dlist_n < 0) {
 
166
    if (errno == ENOENT) {
 
167
      free(dirname);
 
168
      return;
 
169
    } else
 
170
      ohshite(_("error opening configuration directory '%s'"), dirname);
 
171
  }
 
172
 
 
173
  for (i = 0; i < dlist_n; i++) {
 
174
    char *filename;
 
175
 
 
176
    filename = m_malloc(strlen(dirname) + 1 + strlen(dlist[i]->d_name) + 1);
 
177
    sprintf(filename, "%s/%s", dirname, dlist[i]->d_name);
 
178
 
 
179
    myfileopt(filename, cmdinfos);
 
180
 
 
181
    free(filename);
 
182
  }
 
183
 
 
184
  free(dirname);
 
185
  free(dlist);
 
186
}
 
187
 
 
188
void loadcfgfile(const char *prog, const struct cmdinfo* cmdinfos) {
 
189
  char *home, *file;
 
190
  int l1, l2;
 
191
 
 
192
  load_config_dir(prog, cmdinfos);
 
193
 
 
194
  l1 = strlen(CONFIGDIR "/.cfg") + strlen(prog);
 
195
  file = m_malloc(l1 + 1);
 
196
  sprintf(file, CONFIGDIR "/%s.cfg", prog);
 
197
  myfileopt(file, cmdinfos);
 
198
  if ((home = getenv("HOME")) != NULL) {
 
199
    l2 = strlen(home) + 1 + strlen("/.cfg") + strlen(prog);
 
200
    if (l2 > l1) {
 
201
      free(file);
 
202
      file = m_malloc(l2 + 1);
 
203
    }
 
204
    sprintf(file, "%s/.%s.cfg", home, prog);
 
205
    myfileopt(file, cmdinfos);
 
206
  }
 
207
  free(file);
 
208
}
 
209
 
 
210
void myopt(const char *const **argvp, const struct cmdinfo *cmdinfos) {
 
211
  const struct cmdinfo *cip;
 
212
  const char *p, *value;
 
213
  int l;
 
214
 
 
215
  ++(*argvp);
 
216
  while ((p= **argvp) && *p == '-') {
 
217
    ++(*argvp);
 
218
    if (!strcmp(p,"--")) break;
 
219
    if (*++p == '-') {
 
220
      ++p; value=NULL;
 
221
      for (cip= cmdinfos;
 
222
           cip->olong || cip->oshort;
 
223
           cip++) {
 
224
        if (!cip->olong) continue;
 
225
        if (!strcmp(p,cip->olong)) break;
 
226
        l= strlen(cip->olong);
 
227
        if (!strncmp(p,cip->olong,l) &&
 
228
            (p[l]== ((cip->takesvalue==2) ? '-' : '='))) { value=p+l+1; break; }
 
229
      }
 
230
      if (!cip->olong) badusage(_("unknown option --%s"),p);
 
231
      if (cip->takesvalue) {
 
232
        if (!value) {
 
233
          value= *(*argvp)++;
 
234
          if (!value) badusage(_("--%s option takes a value"),cip->olong);
 
235
        }
 
236
        if (cip->call) cip->call(cip,value);
 
237
        else *cip->sassignto= value;
 
238
      } else {
 
239
        if (value) badusage(_("--%s option does not take a value"),cip->olong);
 
240
        if (cip->call) cip->call(cip,NULL);
 
241
        else *cip->iassignto= cip->arg;
 
242
      }
 
243
    } else {
 
244
      while (*p) {
 
245
        for (cip= cmdinfos; (cip->olong || cip->oshort) && *p != cip->oshort; cip++);
 
246
        if (!cip->oshort) badusage(_("unknown option -%c"),*p);
 
247
        p++;
 
248
        if (cip->takesvalue) {
 
249
          if (!*p) {
 
250
            value= *(*argvp)++;
 
251
            if (!value) badusage(_("-%c option takes a value"),cip->oshort);
 
252
          } else {
 
253
            value= p; p="";
 
254
            if (*value == '=') value++;
 
255
          }
 
256
          if (cip->call) cip->call(cip,value);
 
257
          else *cip->sassignto= value;
 
258
        } else {
 
259
          if (*p == '=') badusage(_("-%c option does not take a value"),cip->oshort);
 
260
          if (cip->call) cip->call(cip,NULL);
 
261
          else *cip->iassignto= cip->arg;
 
262
        }
 
263
      }
 
264
    }
 
265
  }
 
266
}