blog/archives/2009/04zack's home pagehttp://upsilon.cc/~zack/blog/archives/2009/04/zack's home pageikiwiki2015-05-18T18:34:23Zhowto: uploading to people.d.o using dputhttp://upsilon.cc/~zack/blog/posts/2009/04/howto:_uploading_to_people.d.o_using_dput/2015-05-18T18:34:23Z2009-04-24T12:30:15Z
<h1>dput + mini-dinstall to ease people.d.o uploads</h1>
<p>As DDs we often want to offer <em>unofficial</em> packages, but
still preserving a bit of "authoritativeness". A widespread
solution is to upload somewhere under <a href=
"https://people.debian.org/~LOGIN">https://people.debian.org/~LOGIN</a>
as an APT repository.</p>
<p>I've been using that solution too since ... ever, but I've never
been happy about how to advertise the packages, probably just
because I've never liked <code>dpkg-scan{packages,sources}</code>
and hackish scripts built on top of them. My goal, as simple as it
can be, is to work as I do to prepare "real" packages to be
uploaded to the Debian archive, and just upload to people.d.o as
the final step.</p>
<p>Thanks to DSA which satisfied a request of mine by installing a
while ago <a href=
"http://packages.debian.org/sid/mini-dinstall">mini-dinstall</a> on
ravel, today I've finally set up a work-flow that enabled me to
reach my goal. This post is a quick howto to implement that
setup.</p>
<p>If you have suggestions about where (wiki.d.o? devref?) to paste
these info so that other DDs can more easily find them in the
future, please let me know, via comments or mailing me.</p>
<h2>Step 1: configure mini-dinstall on people.debian.org</h2>
<p>On people.debian.org, create a ~/.mini-dinstall.conf file
containing something like the following:</p>
<pre><code> [DEFAULT]
mail_to = zack
incoming_permissions = 0750
architectures = all, i386, amd64
archive_style = flat
dynamic_reindex = 1
archivedir = /home/zack/public_html/debian/
generate_release = 1
release_origin = Zack
release_label = Zack
release_description = Unofficial Debian packages maintained by Stefano Zacchiroli
[zack-unstable]
release_suite = zack-unstable
</code></pre>
<p>Highlights of that conf:</p>
<ul>
<li>"flat" archive style means "all in one dir", a more structured
alternative is "simple-subdir"</li>
<li>you request to generate a <code>Release</code> file, which is
needed for the secure APT machinery; various fields of that file
are specified by the <code>release_*</code> options</li>
<li>you call your suite "zack-unstable" (well, I do <img src=
"http://upsilon.cc/~zack/smileys/smile.png" alt=":-)" /> ). That suite must
match the distribution in your <code>debian/changelog</code>
entries. In theory you can use legacy names such as "unstable", but
as we are humans and we make mistakes, better to use invalid suite
names that will be refused by dak if you upload to the wrong
queue</li>
</ul>
<p>The resulting repository will be accessible using the following
<code>/etc/apt/sources.list</code> lines:</p>
<pre><code> deb https://people.debian.org/~zack/debian zack-unstable/
deb-src https://people.debian.org/~zack/debian zack-unstable/
</code></pre>
<h2>Step 2: configure dput</h2>
<p>The default incoming dir of mini-dinstall, relative to the
configured archivedir, is <code>mini-dinstall/incoming</code>. The
following entry for your <code>~/.dput.cf</code> (on the machine
you upload from) will therefore setup your <a href=
"http://packages.debian.org/sid/dput">dput</a> for uploads:</p>
<pre><code> [people.debian.org]
fqdn = people.debian.org
method = scp
login = *
incoming = /home/zack/public_html/debian/mini-dinstall/incoming
post_upload_command = ssh people.debian.org mini-dinstall -b
</code></pre>
<p>The only interesting detail here is the post upload command,
which will run a "pulse" of mini-dinstall on people.d.o just after
the upload, to process the uploaded file. Alternatively, you can
leave mini-dinstall running on people.d.o, but I consider it
unnecessary (because usually you are the only one able to upload to
your home dir), unelegant, and complicated (because you then need
to verify mini-dinstall is running).</p>
<h2>Step 3: enjoy (i.e., upload)</h2>
<p>Now you can prepare your packages as you always do (which means
using <a href=
"http://packages.debian.org/sid/cowbuilder">cowbuilder</a>!) and,
when you are done with your <code>foo_1.0-1_amd64.changes</code>,
upload it doing:</p>
<pre><code> $ dput people.debian.org foo_1.0-1_amd64.changes
</code></pre>
<h2>Signing the Release file</h2>
<p>The above setup does not sign <code>Release</code> files, which
means your APT users will receive complaints from the secure APT
machinery. To fix that you must sign the <code>Release</code> file
with some key and distribute the key to your users to be processed
by <code>apt-key add</code>.</p>
<p>You have a couple of ways to sign the release file
automatically:</p>
<ol>
<li>
<p><small>(/me doesn't like this)</small> use a GPG key created for
the occasion, store that key (including the private part) on
people.d.o, and use the mini-dinstall contrib script <a href=
"http://upsilon.cc/~zack/blog/posts/2009/04/howto:_uploading_to_people.d.o_using_dput/sign-release.sh">
sign-release.sh</a> by adding something like the following to your
<code>mini-dinstall.conf</code>:</p>
<pre><code> release_signscript = ~/bin/sign-release.sh
</code></pre></li>
<li>
<p><small>(/me likes this)</small> use some script to sign the
Release file remotely and send the resulting deatched signature
back to people.d.o just after the mini-dinstall pulse; that way you
can sign with your own private key, which will be reasonably felt
as more trustworthy, being part of the Debian keyring.</p>
</li>
</ol>
<p>To achieve that, the most elegant way would be to fix debsign
wishlist <a href=
"http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=465240">#465240</a>
(volunteers? <img src="http://upsilon.cc/~zack/smileys/smile.png" alt=":-)" />
). As I'm lazy, I'm using my own <a href=
"http://upsilon.cc/~zack/blog/posts/2009/04/howto:_uploading_to_people.d.o_using_dput/sign-remote">
sign-remote</a> script, which is a bit more generic. Remote signing
should be attached to dput upload hook as well. All in all, here is
my actual <code>~/.dput.cf</code> stanza:</p>
<pre><code> [people.debian.org]
fqdn = people.debian.org
method = scp
login = *
incoming = /home/zack/public_html/debian/mini-dinstall/incoming
post_upload_command = ssh people.debian.org "mini-dinstall --batch" && sign-remote people.debian.org:~/public_html/debian/zack-unstable/Release
</code></pre>
<p>Enjoy!</p>
<p><strong>Update</strong>: do both mini-dinstall run and signing
in <code>post_upload_command</code>, following gregoa's suggestion
via comment</p>
<p><strong>Update 2015/05/18</strong>: switch sources.list lines to
https, as suggested by Santiago in comments</p>
alemanno e delanoehttp://upsilon.cc/~zack/blog/posts/2009/04/alemanno_e_delanoe/2009-04-24T11:15:11Z2009-04-24T09:08:19Z
<p>Delanoe, attuale sindaco di Parigi, riferendosi all'attuale
sindaco di Roma, <a href=
"http://www.lastampa.it/redazione/cmsSezioni/politica/200904articoli/43091girata.asp">
ha dichiarato</a>:</p>
<p><q>Difficilmente potrò avere il rapporto che avevo con Rutelli e
Veltroni con un sindaco che ha esordito in Campidoglio con il
saluto fascista.</q></p>
<p>Alemanno, sindaco di Roma, <a href=
"http://www.repubblica.it/2009/04/sezioni/politica/alemanno-delanoe/alemanno-anais/alemanno-anais.html">
ha risposto</a>:</p>
<p><q>Quello che ha detto il sindaco di Parigi su di me è
<strong>falso</strong>, offensivo e intollerabile.</q></p>
<p><big><a href=
"http://roma.repubblica.it/multimedia/home/2117682/1">Ah
si?</a></big></p>
happy term Stevehttp://upsilon.cc/~zack/blog/posts/2009/04/happy_term_Steve/2009-11-28T12:00:16Z2009-04-16T08:55:35Z
<h1>DPL candidacy woes</h1>
<p>Well, time to face it publicly: <a href=
"http://www.debian.org/vote/2009/vote_001">I lost and Steve/Luk
won</a>, it is as simple as that <img src=
"http://upsilon.cc/~zack/smileys/smile.png" alt=":-)" /></p>
<p>This post is to:</p>
<ul>
<li>
<p>congratulate with Steve and Luk for the result, I wish you
<a href="http://blog.einval.com/2009/04/13#whoops">a happy and
fruitful DPL term</a></p>
</li>
<li>
<p>thanks all the people which supported me, in particular:</p>
<ul>
<li>
<p>lucas, paravoid, and gismo: my candidacy started as a typical
"DebConf joke"; if then it has become a reality is for friends like
them insisting (or pretending :-P) I was up to the task. Actually,
I'm quite happy about the result, so it was definitely worth
trying!</p>
</li>
<li>
<p>all the people which contributed comments for my platform, a
list in no particular order follows (in the hope of not having
forgot anyone!): madduck, enrico, lucas, tbm, godog, gismo, gregoa,
dato, ralf, paravoid, buxy. Thank you guys, my platform would have
been much worst without your input.</p>
</li>
<li>
<p>all the people who voted for me (of course!)</p>
</li>
</ul>
</li>
</ul>
<p>All in all, standing for DPL has been worth and interesting no
matter the result.</p>
<p>Time to get back to my usual Debian duties now ...</p>
berlusconi scosso dal terremotohttp://upsilon.cc/~zack/blog/posts/2009/04/berlusconi_scosso_dal_terremoto/2009-04-15T20:56:12Z2009-04-15T17:35:10Z
<h1>dalla <a href=
"http://www.lecanardenchaine.fr/une4616.html"><em>prima
pagina</em></a> di <a href=
"http://en.wikipedia.org/wiki/Le_Canard_Encha%C3%AEn%C3%A9">Le
Canard Enchainé</a> di oggi ...</h1>
<p><a href=
"http://upsilon.cc/~zack/blog/posts/2009/04/berlusconi_scosso_dal_terremoto/canard-berlusconi-2009-04-15.jpg">
<img src=
"http://upsilon.cc/~zack/blog/posts/2009/04/berlusconi_scosso_dal_terremoto/772x-canard-berlusconi-2009-04-15.jpg"
width="771" height="383" class="img" /></a></p>
<p>Vi risparmio la traduzione per non perdere di poesia, ma
(inevitabilmente) l'articolo ripercorre tutte le recenti gag del
nostro. Nell'ordine:</p>
<ul>
<li>il week-end in camping per i terremotati</li>
<li>festeggiare la Pasqua al mare</li>
<li>l'offerta delle sue case ai senza tetto</li>
<li>L'Aquila 2</li>
</ul>
xmonad + gnome on Debianhttp://upsilon.cc/~zack/blog/posts/2009/04/xmonad_+_gnome_on_Debian/2009-11-28T12:00:16Z2009-04-15T11:21:35Z
<h1>... finally I'm tiling too!</h1>
<p><strong>Short story</strong>: I've just switched to <a href=
"http://www.xmonad.org">xmonad</a> as my window manager of choice
within a <a href="http://www.gnome.org">Gnome</a> desktop
environment; I give some tips on how to achieve that quickly on a
current Debian/unstable machine.</p>
<h2>/me and tiling window managers</h2>
<p>I switched to Gnome a long time ago. The benefit of that over
good old window managers is enjoying an integrated environment and
a workplace that you can find on other machines (e.g., the netbook
you installed for your mother, the office desktop, the student lab
machines, ...). Still, I've never been particularly happy about
Gnome's default window manager: <a href=
"http://en.wikipedia.org/wiki/Metacity">metacity</a>. The feature I
was missing the most is the ability to configure windows
programmatically so that they appear where and how I want by
default; sadly enough, the Gnome session mechanism is not yet able
to do that properly.</p>
<p>Hence, I've tried various time switching to a tiling window
manager, imposing the extra requirement that it should integrate
with Gnome. The coolest guy on the block of that area seems to be
<a href="http://awesome.naquadah.org/">awesome</a> and I gave it a
try some months ago. I liked most of its (sometime revolutionary)
principles, like window tagging, but I equally hated various
aspects of it:</p>
<ul>
<li>
<p><em>Documentation</em> back then was horrible, starting from the
manpage speaking of mod{1,2,3,4,5} without giving a hint about
where the heck they are mapped to by default, ranging to the lack
of references manual about what you can call from LUA configuration
files. ... use the source, Luke ...</p>
</li>
<li>
<p><em>Community</em> was mainly composed by super-users, which is
good if you want to do some super-configuration. ... but is deeply
bad™ if you are trying to get hints on how to make awesome cope
with Gnome. I remember having been treated as a total luser on IRC,
with people more interested in convincing me that I should stop
using Gnome than in helping out achieving what I wanted to.</p>
</li>
</ul>
<p>People nowadays tell me that awesome works fine with Gnome, so
maybe I've just been unlucky back then, but sometime the first
impression does count.</p>
<p>I've never considered seriously <a href=
"http://www.xmonad.org">xmonad</a>, thinking (with no sound reason,
apparently) that it was a project of the series: "I'm a fan of
programming language $LANG, all my apps should be written in $LANG,
my window manager is no exception", with LANG=haskell.</p>
<p>Then two things happened:</p>
<ol>
<li>
<p>a couple of weeks ago I stumbled upon the xmonad <a href=
"http://www.haskell.org/haskellwiki/Xmonad">wiki</a> and <a href=
"http://xmonad.org/documentation.html">documentation</a>, and I was
impressed by the average quality of the information shipped there.
It is not something you usually find in "language showcase"
projects.</p>
</li>
<li>
<p><a href=
"http://justimho.blogspot.com/search/label/Debian">Patrick</a>
blogged about its switch to <a href=
"http://justimho.blogspot.com/2009/04/gnomad-gnome-xmonad.html">xmonad
+ Gnome</a>, with enthusiastic feedback. If that's not a sign I
don't know what it can be <img src="http://upsilon.cc/~zack/smileys/smile.png"
alt=":-)" /></p>
</li>
</ol>
<h2>Getting started with xmonad + Gnome on Debian</h2>
<p>There is <a href=
"http://www.haskell.org/haskellwiki/Xmonad/Using_xmonad_in_Gnome">a
page</a> explaining how to use xmonad with Gnome in the xmonad
wiki, but a handful of additional tips will help you get started in
Debian, even if you know (almost) nothing about Haskell (yet).</p>
<ul>
<li>You should install <strong>packages</strong> <a href=
"http://packages.debian.org/sid/xmonad">xmonad</a> <em>and</em>
<a href=
"http://packages.debian.org/sid/libghc6-xmonad-dev">libghc6-xmonad-dev</a>.
Without the latter <em>you will not be able to configure</em> your
xmonad; in particular you will not have access to the Gnome
configuration library, which offers sane defaults for using xmonad
with Gnome. <small>(See below for a rant on the disk usage of
installing the second package ...)</small></li>
</ul>
<p>The (crazy) way in which xmonad works is that you create your
config file as <code>~/.xmonad/xmonad.hs</code>. That file is a
full fledged Haskell program, which gets compiled to obtain your
own xmonad executable which you run as your own window manager.
<code>/usr/bin/xmonad</code> is the executable you initially run,
but is just a wrapper around the compilation + run mechanism</p>
<ul>
<li>
<p>Since you have installed libghc6-xmonad-dev, you have access to
a module pre-<strong>configuring xmonad for Gnome</strong>, just
use the following as your starting xmonad.hs:</p>
<pre><code> import XMonad
import XMonad.Config.Gnome
main = xmonad $ gnomeConfig {
modMask = mod4Mask
}
</code></pre></li>
</ul>
<p>The modMask setting means that ALT will get delivered to
applications, while all xmonad commands are delivered via the
infamous windows key: no more conflicts between apps and WM
<code>\o/</code>.</p>
<ul>
<li>At this point you can <strong>configure xmonad as your Gnome
window manager</strong>. Disable re-spawning of metacity in your
session option, and run somewhere <code>killall metacity ; xmonad
&</code> . For the next session runs you will have to remember
the running xmonad in your Gnome session, as usual.</li>
</ul>
<p>The default Gnome configuration is quite nice: you can retain
your Nautilus desktop (in spite of <a href=
"http://www.haskell.org/haskellwiki/Xmonad/Using_xmonad_in_Gnome">what
is written on the wiki</a>), <code>mod-p</code> will get you a
gnome-run dialog box, and appropriate padding for the (upper!)
Gnome panel.</p>
<p>The only glitch is that you will get 9 desktops which can
clutter your workspace switched. My solution is to have the appler
show workspaces on 2 rows but <strong>beware of bug <a href=
"http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=524065">524065</a></strong>,
which is <em>really</em> annoying.</p>
<ul>
<li>
<p><strong>Compositing</strong> works as well, by the means of
<a href="http://packages.debian.org/sid/xcompmgr">xcompmgr</a>.
Just install it and register in your session the result of running
<code>xcompmgr -c &</code>. No wonder that it is way faster
than compositing manager support in metacity.</p>
</li>
<li>
<p>Finally, you can <strong>configure window placement</strong> in
your xmonad.hs by doing something like the following (it already
includes the shorter snippet given before):</p>
<pre><code> import XMonad
import XMonad.Config.Gnome
myManageHook = composeAll [
(className =? "Pidgin" <&&> title =? "Buddy List") --> doFloat
, (className =? "Gnome-panel" <&&> title =? "Run Application") --> doFloat
-- , (className =? "XEyes") --> doShift "7"
]
main = xmonad $ gnomeConfig {
modMask = mod4Mask
, manageHook = myManageHook <+> manageHook gnomeConfig
}
</code></pre></li>
</ul>
<p>The above example will make the pidgin buddy list and run
application dialog box float by default. The commented line is an
example of how to deliver specific windows to arbitrary workspaces.
To find out window properties on which match in your xmonad.hs, my
magic command is <code>xprop | egrep "CLASS|NAME"</code>.</p>
<p>Note that you don't need to care about panel placement because
it is already taken care of by the default gnome config. Still
beware of not using myManageHook as your <em>only</em> management
hook, you should <em>update</em> the default one using the
<code><+></code> monad as I did above.</p>
<h2>xmonad rant</h2>
<p>So, what's wrong with xmonad + Gnome in Debian? Well, the fact
that it will take about 200 Mb of disk space on amd64 by default.
<code>o_O</code></p>
<p>Why so? Because xmonad is affected by the <em>static linking
hell</em> which seems to be shared by modern statically typed
functional languages, including in the category both Haskell and my
beloved OCaml. In short, applications written for those language
link statically code written in the implementation language in most
cases; they rely on legacy shared libraries only for bindings to C
libraries.</p>
<p>For xmonad that means that if you are fine with the default
configuration you will get a cheap 2 Mb binary package. If you are
not, you will need to write your conffile ... which is a Haskell
program ... using several contrib libraries ... and needing ghc6 to
be compiled and run as your own window manager executable.</p>
<p>This is plainly dumb and induces all the usual problems of
static linking, like disk consumption due to non-shared (Haskell)
code, and worries about staying up to date with the latest library
release in case of fixes (including <em>security</em> fixes) need
to be propagated to user executables.</p>
<p>Truth to be said, <code>/usr/bin/xmonad</code> does a wonderful
job in hiding all this to the final user, but still the design
choice is an unpleasant one.</p>
ocaml 3.11 in testinghttp://upsilon.cc/~zack/blog/posts/2009/04/ocaml_3.11_in_testing/2009-11-28T12:00:16Z2009-04-06T11:17:11Z
<h1>OCaml 3.11 has migrated to testing</h1>
<p><a href=
"http://lists.debian.org/debian-ocaml-maint/2009/04/msg00029.html">Quoting</a>
from <a href=
"http://chistera.yi.org/~adeodato/blog/planetd.html">Dato</a>:</p>
<pre><code>* Stéphane Glondu [Sat, 04 Apr 2009 14:01:35 +0200]:
> Adeodato Simó a écrit :
> >> Please schedule the attached requests for the OCaml 3.11.0 transition.
> > Scheduled, with the glitches noted below. Please get back to us with the
> > needed wanna-build actions.
> All packages that needed recompilation or sourceful uploads for the
> OCaml 3.11.0 transition are now compiled and available in unstable.
> I guess migrating ocaml to testing can now be considered...
This is now done:
ocaml | 3.11.0-5 | testing
ocaml | 3.11.0-5 | unstable
Congratulations for making of this transition one of the less painful
I’ve ever had to deal with, though I guess being a quite self-contained
set of packages and not having ties to other ongoing
transitions really
helped. ;-)
Thanks!,
</code></pre>
<p>IOW <strong>OCaml 3.11 has just migrated to Debian
testing</strong> YAY \o/</p>
<p>Congrats and thanks to all the people who contributed. Special
kudos go to the (not so) newbies of the <a href=
"http://wiki.debian.org/Teams/OCamlTaskForce">Debian OCaml Task
Force</a>, and in particular to <em>Stephane Glondu</em> and
<em>Mehdi Dogguy</em>: they have contributed work to a lot of
packages and have also developed <a href=
"http://glondu.net/debian/ocaml_transition_monitor.html">new
tools</a> which helped monitoring the transition effectively.</p>
<p>Keep up the good work.</p>
ocaml batteries in Debian unstablehttp://upsilon.cc/~zack/blog/posts/2009/04/ocaml_batteries_in_Debian_unstable/2009-11-28T12:00:16Z2009-04-03T08:35:02Z
<h1>batteries approaching Beta 1: now in unstable</h1>
<p><a href=
"http://upsilon.cc/~zack/blog/posts/2008/10/ocaml_batteries_included_debian_packages/">It's
been a while</a>, but work on <a href=
"http://batteries.forge.ocamlcore.org">OCaml batteries included</a>
has continued steadily in the past months. We are now approaching
the first <strong>Beta release</strong>, which is due in a few
days.</p>
<p>In the meantime, a couple of days ago I've uploaded the Debian
<a href=
"http://packages.debian.org/sid/ocaml-batteries-included"><strong>ocaml-batteries
package</strong></a> to the unstable archive for the first time (it
was only available from experimental thus far). It is an “almost
Beta” release which you are <strong>encouraged to test</strong>
both for packaging aspects and for having a feeling of what
batteries will look like in its final shape.</p>
<p>To <strong>get started</strong> just do the following:</p>
<pre><code># aptitude install ocaml-batteries-included
$ ledit ocaml-batteries
</code></pre>
ocaml autoconf 1.0http://upsilon.cc/~zack/blog/posts/2009/04/ocaml_autoconf_1.0/2009-11-28T12:00:16Z2009-04-01T08:15:30Z
<h1>1st release of <code>ocaml-autoconf</code></h1>
<p>A couple of months ago, I joined an effort by <a href=
"http://www.annexia.org/richard_w.m._jones">Richard Jones</a> to
give a decent shape to <strong><a href=
"http://www.gnu.org/software/autoconf/">autoconf</a> macros for
OCaml</strong>. The situation was a tad annoying before, because we
had unofficial <code>ocaml.m4</code> files floating around, which
have diverged one from another, with unclear licensing terms,
incompatible features, ecc.</p>
<p>So we started a <a href=
"http://ocaml-autoconf.forge.ocamlcore.org">project on the
ocamlforge</a> to coordinate all this, injected the best we could
find around, add <a href=
"http://forge.ocamlcore.org/docman/index.php?group_id=69&selected_doc_group_id=103&language_id=1">
docs</a>, polish features, and contacted copyright owner to uniform
licensing terms (to a <strong>3-clause BSD</strong>).</p>
<p>Yesterday we finally <a href=
"http://forge.ocamlcore.org/forum/forum.php?forum_id=324"><strong>released</strong></a>
<a href=
"http://forge.ocamlcore.org/frs/download.php/181/ocaml-autoconf-1.0.tar.gz">
<strong><code>ocaml-autoconf</code> 1.0</strong></a>. <a href=
"http://rwmj.wordpress.com/2009/03/31/using-autoconf-for-ocaml-projects/">
Rich's blog post on the subject</a> contains a nice <strong>how
to</strong> to kick start your OCaml project using autotools up to
automake.</p>
<p>A brief feature overview is in order:</p>
<ul>
<li>single macro to detect main executables of the ocaml
<em>toolchain and whether</em> native code compilation* is
available or not</li>
<li><em>cross-compilation</em> support</li>
<li><em>findlib</em> detection and <em>package</em> checking, with
support for <em>alternative package names</em> (e.g. "zip" vs
"camlzip" on GODI vs Debian)</li>
<li>detection of <em>OCaml module</em> by module path</li>
</ul>
<p>Enjoy, and give us feedback (bug reports, feature requests, ...)
using <a href="http://forge.ocamlcore.org/tracker/?group_id=69">our
tracker</a>.</p>