qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/3] chardev cleanups
@ 2016-06-16 11:17 marcandre.lureau
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 1/3] char: clean up remaining chardevs when leaving marcandre.lureau
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: marcandre.lureau @ 2016-06-16 11:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, berrange, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Hi

A small series to do some chardev cleanup when removing them and
leaving qemu.

Fixes:
https://bugzilla.redhat.com/show_bug.cgi?id=1347077

Marc-André Lureau (3):
  char: clean up remaining chardevs when leaving
  socket: add listen feature
  socket: unlink unix socket on remove

 include/io/channel.h           |  1 +
 include/qemu/sockets.h         |  1 +
 include/sysemu/char.h          |  7 +++++++
 io/channel-socket.c            | 17 +++++++++++++++++
 qemu-char.c                    |  9 +++++++++
 tests/test-io-channel-socket.c |  2 +-
 util/qemu-sockets.c            | 18 ++++++++++++++++++
 vl.c                           |  1 +
 8 files changed, 55 insertions(+), 1 deletion(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 1/3] char: clean up remaining chardevs when leaving
  2016-06-16 11:17 [Qemu-devel] [PATCH 0/3] chardev cleanups marcandre.lureau
@ 2016-06-16 11:17 ` marcandre.lureau
  2016-06-16 12:19   ` Paolo Bonzini
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 2/3] socket: add listen feature marcandre.lureau
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 3/3] socket: unlink unix socket on remove marcandre.lureau
  2 siblings, 1 reply; 8+ messages in thread
From: marcandre.lureau @ 2016-06-16 11:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, berrange, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

This helps to remove various chardev resources leaks when leaving qemu.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/sysemu/char.h | 7 +++++++
 qemu-char.c           | 9 +++++++++
 vl.c                  | 1 +
 3 files changed, 17 insertions(+)

diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 372a6fd..8954be1 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -382,6 +382,13 @@ void qemu_chr_be_write_impl(CharDriverState *s, uint8_t *buf, int len);
  */
 void qemu_chr_be_event(CharDriverState *s, int event);
 
+/**
+ * @qemu_chr_cleanup:
+ *
+ * Delete all chardevs (when leaving qemu)
+ */
+void qemu_chr_cleanup(void);
+
 void qemu_chr_add_handlers(CharDriverState *s,
                            IOCanReadHandler *fd_can_read,
                            IOReadHandler *fd_read,
diff --git a/qemu-char.c b/qemu-char.c
index b13ecbb..bf098a1 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -4088,6 +4088,15 @@ CharDriverState *qemu_chr_find(const char *name)
     return NULL;
 }
 
+void qemu_chr_cleanup(void)
+{
+    CharDriverState *chr;
+
+    QTAILQ_FOREACH(chr, &chardevs, next) {
+        qemu_chr_delete(chr);
+    }
+}
+
 QemuOptsList qemu_chardev_opts = {
     .name = "chardev",
     .implied_opt_name = "backend",
diff --git a/vl.c b/vl.c
index 45eff56..ac92b1d 100644
--- a/vl.c
+++ b/vl.c
@@ -4628,6 +4628,7 @@ int main(int argc, char **argv, char **envp)
 #ifdef CONFIG_TPM
     tpm_cleanup();
 #endif
+    qemu_chr_cleanup();
 
     return 0;
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 2/3] socket: add listen feature
  2016-06-16 11:17 [Qemu-devel] [PATCH 0/3] chardev cleanups marcandre.lureau
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 1/3] char: clean up remaining chardevs when leaving marcandre.lureau
@ 2016-06-16 11:17 ` marcandre.lureau
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 3/3] socket: unlink unix socket on remove marcandre.lureau
  2 siblings, 0 replies; 8+ messages in thread
From: marcandre.lureau @ 2016-06-16 11:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, berrange, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Add a flag to tell whether the channel socket is listening.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/io/channel.h | 1 +
 io/channel-socket.c  | 7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/include/io/channel.h b/include/io/channel.h
index d37acd2..e52f059 100644
--- a/include/io/channel.h
+++ b/include/io/channel.h
@@ -42,6 +42,7 @@ typedef enum QIOChannelFeature QIOChannelFeature;
 enum QIOChannelFeature {
     QIO_CHANNEL_FEATURE_FD_PASS  = (1 << 0),
     QIO_CHANNEL_FEATURE_SHUTDOWN = (1 << 1),
+    QIO_CHANNEL_FEATURE_LISTEN   = (1 << 2),
 };
 
 
diff --git a/io/channel-socket.c b/io/channel-socket.c
index ca8bc20..1cd5848 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -71,6 +71,9 @@ qio_channel_socket_set_fd(QIOChannelSocket *sioc,
                           int fd,
                           Error **errp)
 {
+    int val;
+    socklen_t len = sizeof(val);
+
     if (sioc->fd != -1) {
         error_setg(errp, "Socket is already open");
         return -1;
@@ -106,6 +109,10 @@ qio_channel_socket_set_fd(QIOChannelSocket *sioc,
         ioc->features |= (1 << QIO_CHANNEL_FEATURE_FD_PASS);
     }
 #endif /* WIN32 */
+    if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &val, &len) == 0 && val) {
+        QIOChannel *ioc = QIO_CHANNEL(sioc);
+        ioc->features |= (1 << QIO_CHANNEL_FEATURE_LISTEN);
+    }
 
     return 0;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 3/3] socket: unlink unix socket on remove
  2016-06-16 11:17 [Qemu-devel] [PATCH 0/3] chardev cleanups marcandre.lureau
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 1/3] char: clean up remaining chardevs when leaving marcandre.lureau
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 2/3] socket: add listen feature marcandre.lureau
@ 2016-06-16 11:17 ` marcandre.lureau
  2016-06-16 12:28   ` Paolo Bonzini
  2 siblings, 1 reply; 8+ messages in thread
From: marcandre.lureau @ 2016-06-16 11:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, berrange, Marc-André Lureau

From: Marc-André Lureau <marcandre.lureau@redhat.com>

qemu leaves unix socket files behind when removing a listening chardev
or leaving. qemu could clean that up, even if doing so isn't race-free.

Fixes:
https://bugzilla.redhat.com/show_bug.cgi?id=1347077

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qemu/sockets.h         |  1 +
 io/channel-socket.c            | 10 ++++++++++
 tests/test-io-channel-socket.c |  2 +-
 util/qemu-sockets.c            | 18 ++++++++++++++++++
 4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 1bd9218..5dd2648 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -51,6 +51,7 @@ SocketAddress *socket_parse(const char *str, Error **errp);
 int socket_connect(SocketAddress *addr, Error **errp,
                    NonBlockingConnectHandler *callback, void *opaque);
 int socket_listen(SocketAddress *addr, Error **errp);
+void socket_listen_cleanup(int fd, Error **errp);
 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
 
 /* Old, ipv4 only bits.  Don't use for new code. */
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 1cd5848..319e1ab 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -400,7 +400,17 @@ static void qio_channel_socket_init(Object *obj)
 static void qio_channel_socket_finalize(Object *obj)
 {
     QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
+
     if (ioc->fd != -1) {
+        Error *err = NULL;
+
+        if (QIO_CHANNEL(ioc)->features & QIO_CHANNEL_FEATURE_LISTEN)
+            socket_listen_cleanup(ioc->fd, &err);
+
+        if (err) {
+            error_report_err(err);
+            err = NULL;
+        }
 #ifdef WIN32
         WSAEventSelect(ioc->fd, NULL, 0);
 #endif
diff --git a/tests/test-io-channel-socket.c b/tests/test-io-channel-socket.c
index 855306b..f73e063 100644
--- a/tests/test-io-channel-socket.c
+++ b/tests/test-io-channel-socket.c
@@ -383,7 +383,7 @@ static void test_io_channel_unix(bool async)
 
     qapi_free_SocketAddress(listen_addr);
     qapi_free_SocketAddress(connect_addr);
-    unlink(TEST_SOCKET);
+    g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS) == FALSE);
 }
 
 
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 0d6cd1f..5d03695 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -997,6 +997,24 @@ int socket_listen(SocketAddress *addr, Error **errp)
     return fd;
 }
 
+void socket_listen_cleanup(int fd, Error **errp)
+{
+    SocketAddress *addr;
+
+    addr = socket_local_address(fd, errp);
+
+    if (addr->type == SOCKET_ADDRESS_KIND_UNIX
+        && addr->u.q_unix.data->path) {
+        if (unlink(addr->u.q_unix.data->path) < 0 && errno != ENOENT) {
+            error_setg_errno(errp, errno,
+                             "Failed to unlink socket %s",
+                             addr->u.q_unix.data->path);
+        }
+    }
+
+    g_free(addr);
+}
+
 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
 {
     int fd;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 1/3] char: clean up remaining chardevs when leaving
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 1/3] char: clean up remaining chardevs when leaving marcandre.lureau
@ 2016-06-16 12:19   ` Paolo Bonzini
  2016-06-16 12:25     ` Marc-André Lureau
  0 siblings, 1 reply; 8+ messages in thread
From: Paolo Bonzini @ 2016-06-16 12:19 UTC (permalink / raw)
  To: marcandre.lureau, qemu-devel



On 16/06/2016 13:17, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> This helps to remove various chardev resources leaks when leaving qemu.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/sysemu/char.h | 7 +++++++
>  qemu-char.c           | 9 +++++++++
>  vl.c                  | 1 +
>  3 files changed, 17 insertions(+)
> 
> diff --git a/include/sysemu/char.h b/include/sysemu/char.h
> index 372a6fd..8954be1 100644
> --- a/include/sysemu/char.h
> +++ b/include/sysemu/char.h
> @@ -382,6 +382,13 @@ void qemu_chr_be_write_impl(CharDriverState *s, uint8_t *buf, int len);
>   */
>  void qemu_chr_be_event(CharDriverState *s, int event);
>  
> +/**
> + * @qemu_chr_cleanup:
> + *
> + * Delete all chardevs (when leaving qemu)
> + */
> +void qemu_chr_cleanup(void);
> +
>  void qemu_chr_add_handlers(CharDriverState *s,
>                             IOCanReadHandler *fd_can_read,
>                             IOReadHandler *fd_read,
> diff --git a/qemu-char.c b/qemu-char.c
> index b13ecbb..bf098a1 100644
> --- a/qemu-char.c
> +++ b/qemu-char.c
> @@ -4088,6 +4088,15 @@ CharDriverState *qemu_chr_find(const char *name)
>      return NULL;
>  }
>  
> +void qemu_chr_cleanup(void)
> +{
> +    CharDriverState *chr;
> +
> +    QTAILQ_FOREACH(chr, &chardevs, next) {
> +        qemu_chr_delete(chr);
> +    }
> +}
> +
>  QemuOptsList qemu_chardev_opts = {
>      .name = "chardev",
>      .implied_opt_name = "backend",
> diff --git a/vl.c b/vl.c
> index 45eff56..ac92b1d 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -4628,6 +4628,7 @@ int main(int argc, char **argv, char **envp)
>  #ifdef CONFIG_TPM
>      tpm_cleanup();
>  #endif
> +    qemu_chr_cleanup();

Given the amount of exit(1) calls surviving in QEMU, it's probably
better to use atexit here.

Paolo

>      return 0;
>  }
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 1/3] char: clean up remaining chardevs when leaving
  2016-06-16 12:19   ` Paolo Bonzini
@ 2016-06-16 12:25     ` Marc-André Lureau
  0 siblings, 0 replies; 8+ messages in thread
From: Marc-André Lureau @ 2016-06-16 12:25 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: marcandre lureau, qemu-devel, berrange

Hi

----- Original Message -----
> > +
> >  QemuOptsList qemu_chardev_opts = {
> >      .name = "chardev",
> >      .implied_opt_name = "backend",
> > diff --git a/vl.c b/vl.c
> > index 45eff56..ac92b1d 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -4628,6 +4628,7 @@ int main(int argc, char **argv, char **envp)
> >  #ifdef CONFIG_TPM
> >      tpm_cleanup();
> >  #endif
> > +    qemu_chr_cleanup();
> 
> Given the amount of exit(1) calls surviving in QEMU, it's probably
> better to use atexit here.

Agreed, fixed

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] socket: unlink unix socket on remove
  2016-06-16 11:17 ` [Qemu-devel] [PATCH 3/3] socket: unlink unix socket on remove marcandre.lureau
@ 2016-06-16 12:28   ` Paolo Bonzini
  2016-06-16 12:36     ` Marc-André Lureau
  0 siblings, 1 reply; 8+ messages in thread
From: Paolo Bonzini @ 2016-06-16 12:28 UTC (permalink / raw)
  To: marcandre.lureau, qemu-devel



On 16/06/2016 13:17, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> qemu leaves unix socket files behind when removing a listening chardev
> or leaving. qemu could clean that up, even if doing so isn't race-free.
> 
> Fixes:
> https://bugzilla.redhat.com/show_bug.cgi?id=1347077
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  include/qemu/sockets.h         |  1 +
>  io/channel-socket.c            | 10 ++++++++++
>  tests/test-io-channel-socket.c |  2 +-
>  util/qemu-sockets.c            | 18 ++++++++++++++++++
>  4 files changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
> index 1bd9218..5dd2648 100644
> --- a/include/qemu/sockets.h
> +++ b/include/qemu/sockets.h
> @@ -51,6 +51,7 @@ SocketAddress *socket_parse(const char *str, Error **errp);
>  int socket_connect(SocketAddress *addr, Error **errp,
>                     NonBlockingConnectHandler *callback, void *opaque);
>  int socket_listen(SocketAddress *addr, Error **errp);
> +void socket_listen_cleanup(int fd, Error **errp);
>  int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
>  
>  /* Old, ipv4 only bits.  Don't use for new code. */
> diff --git a/io/channel-socket.c b/io/channel-socket.c
> index 1cd5848..319e1ab 100644
> --- a/io/channel-socket.c
> +++ b/io/channel-socket.c
> @@ -400,7 +400,17 @@ static void qio_channel_socket_init(Object *obj)
>  static void qio_channel_socket_finalize(Object *obj)
>  {
>      QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
> +
>      if (ioc->fd != -1) {
> +        Error *err = NULL;
> +
> +        if (QIO_CHANNEL(ioc)->features & QIO_CHANNEL_FEATURE_LISTEN)
> +            socket_listen_cleanup(ioc->fd, &err);

Every time you forget braces, checkpatch.pl kills a kitten!  Think of
the kittens!

Paolo

> +
> +        if (err) {
> +            error_report_err(err);
> +            err = NULL;
> +        }
>  #ifdef WIN32
>          WSAEventSelect(ioc->fd, NULL, 0);
>  #endif
> diff --git a/tests/test-io-channel-socket.c b/tests/test-io-channel-socket.c
> index 855306b..f73e063 100644
> --- a/tests/test-io-channel-socket.c
> +++ b/tests/test-io-channel-socket.c
> @@ -383,7 +383,7 @@ static void test_io_channel_unix(bool async)
>  
>      qapi_free_SocketAddress(listen_addr);
>      qapi_free_SocketAddress(connect_addr);
> -    unlink(TEST_SOCKET);
> +    g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS) == FALSE);
>  }
>  
>  
> diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
> index 0d6cd1f..5d03695 100644
> --- a/util/qemu-sockets.c
> +++ b/util/qemu-sockets.c
> @@ -997,6 +997,24 @@ int socket_listen(SocketAddress *addr, Error **errp)
>      return fd;
>  }
>  
> +void socket_listen_cleanup(int fd, Error **errp)
> +{
> +    SocketAddress *addr;
> +
> +    addr = socket_local_address(fd, errp);
> +
> +    if (addr->type == SOCKET_ADDRESS_KIND_UNIX
> +        && addr->u.q_unix.data->path) {
> +        if (unlink(addr->u.q_unix.data->path) < 0 && errno != ENOENT) {
> +            error_setg_errno(errp, errno,
> +                             "Failed to unlink socket %s",
> +                             addr->u.q_unix.data->path);
> +        }
> +    }
> +
> +    g_free(addr);
> +}
> +
>  int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
>  {
>      int fd;
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] socket: unlink unix socket on remove
  2016-06-16 12:28   ` Paolo Bonzini
@ 2016-06-16 12:36     ` Marc-André Lureau
  0 siblings, 0 replies; 8+ messages in thread
From: Marc-André Lureau @ 2016-06-16 12:36 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: marcandre lureau, qemu-devel, berrange

Hi

----- Original Message -----
> 
> 
> On 16/06/2016 13:17, marcandre.lureau@redhat.com wrote:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> > 
> > qemu leaves unix socket files behind when removing a listening chardev
> > or leaving. qemu could clean that up, even if doing so isn't race-free.
> > 
> > Fixes:
> > https://bugzilla.redhat.com/show_bug.cgi?id=1347077
> > 
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  include/qemu/sockets.h         |  1 +
> >  io/channel-socket.c            | 10 ++++++++++
> >  tests/test-io-channel-socket.c |  2 +-
> >  util/qemu-sockets.c            | 18 ++++++++++++++++++
> >  4 files changed, 30 insertions(+), 1 deletion(-)
> > 
> > diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
> > index 1bd9218..5dd2648 100644
> > --- a/include/qemu/sockets.h
> > +++ b/include/qemu/sockets.h
> > @@ -51,6 +51,7 @@ SocketAddress *socket_parse(const char *str, Error
> > **errp);
> >  int socket_connect(SocketAddress *addr, Error **errp,
> >                     NonBlockingConnectHandler *callback, void *opaque);
> >  int socket_listen(SocketAddress *addr, Error **errp);
> > +void socket_listen_cleanup(int fd, Error **errp);
> >  int socket_dgram(SocketAddress *remote, SocketAddress *local, Error
> >  **errp);
> >  
> >  /* Old, ipv4 only bits.  Don't use for new code. */
> > diff --git a/io/channel-socket.c b/io/channel-socket.c
> > index 1cd5848..319e1ab 100644
> > --- a/io/channel-socket.c
> > +++ b/io/channel-socket.c
> > @@ -400,7 +400,17 @@ static void qio_channel_socket_init(Object *obj)
> >  static void qio_channel_socket_finalize(Object *obj)
> >  {
> >      QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
> > +
> >      if (ioc->fd != -1) {
> > +        Error *err = NULL;
> > +
> > +        if (QIO_CHANNEL(ioc)->features & QIO_CHANNEL_FEATURE_LISTEN)
> > +            socket_listen_cleanup(ioc->fd, &err);
> 
> Every time you forget braces, checkpatch.pl kills a kitten!  Think of
> the kittens!

Oh no! :) (weird the git hook usually catch this for me), fixed

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2016-06-16 12:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-16 11:17 [Qemu-devel] [PATCH 0/3] chardev cleanups marcandre.lureau
2016-06-16 11:17 ` [Qemu-devel] [PATCH 1/3] char: clean up remaining chardevs when leaving marcandre.lureau
2016-06-16 12:19   ` Paolo Bonzini
2016-06-16 12:25     ` Marc-André Lureau
2016-06-16 11:17 ` [Qemu-devel] [PATCH 2/3] socket: add listen feature marcandre.lureau
2016-06-16 11:17 ` [Qemu-devel] [PATCH 3/3] socket: unlink unix socket on remove marcandre.lureau
2016-06-16 12:28   ` Paolo Bonzini
2016-06-16 12:36     ` Marc-André Lureau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).