ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/contrib/graphtastical.C
Revision: 1.2
Committed: Sat Jul 21 01:29:08 2007 UTC (19 years, 3 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +2 -2 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * Copyright © 2007 William Pitcock
3 pippijn 1.2 * Rights to this code are as documented in doc/pod/license.pod.
4 pippijn 1.1 *
5     * Creates a .dot file for use with neato which displays
6     * user->channel relationships.
7     *
8     * == How to generate the graphs and How It Works ==
9     * Graphtastical creates a .dot file for graphviz's neato
10     * filter to use. The DOT language describes a graph's
11     * structure to graphviz in an opaque way.
12     *
13     * Because Graphviz nodes use unique identifiers for
14     * interconnection, the channels.dot file contains also
15     * information about social networks.
16     *
17     * Eventually Graphtastical will dump other graph datafiles
18     * too.
19     *
20     * To make a file from the data dumped by Graphtastical,
21     * the following commands will do:
22     *
23     * $ cat channels.dot | neato -Tgif -o map-channels.gif
24     * $ cat channels.dot | neato -Tsvg -o map-channels.svg
25     *
26     * Some maps (for larger networks) are going to be large,
27     * so you may want to provide links to both the GIF and
28     * SVG files as some people may only be able to make use of
29     * one or the other. Why that is, I'm not sure, and I'm not
30     * covering it here.
31     *
32     * == Privacy concerns ==
33     * If you are running Graphtastical on a network that has
34     * privacy concerns; you probably shouldn't.
35     */
36    
37     #include "atheme.h"
38     #include <account/chanacs.h>
39     #include <account/mychan.h>
40     #include <account/myuser.h>
41     #include <account/kline.h>
42     #include <account/svsignore.h>
43    
44 pippijn 1.2 DECLARE_MODULE_V1 ("contrib/graphtastical", true, _modinit, NULL, "$Id: graphtastical.C,v 1.1 2007-07-19 08:24:53 pippijn Exp $", "Atheme Development Group <http://www.atheme.org>");
45 pippijn 1.1
46     /* write channels.dot */
47     static void
48     write_channels_dot_file (void *arg)
49     {
50     // myuser_t *mu;
51     mychan_t *mc;
52     chanacs_t *ca;
53     // kline_t *k;
54     // svsignore_t *svsignore;
55     // soper_t *soper;
56     node_t *n;//, *tn, *tn2;
57     FILE *f;
58     int errno1, was_errored = 0;
59     dictionary_iteration_state_t state;
60     int root = 1;
61     mychan_t *pmc;
62    
63     errno = 0;
64    
65     /* write to a temporary file first */
66     if (!(f = fopen (DATADIR "/channels.dot.new", "w")))
67     {
68     errno1 = errno;
69     slog (LG_ERROR, "graphtastical: cannot create channels.dot.new: %s", strerror (errno1));
70     return;
71     }
72    
73     fprintf (f, "graph channels {\n");
74     fprintf (f, "edge [color=blue len=7.5 fontsize=10]\n");
75     fprintf (f, "node [fontsize=10]\n");
76    
77     slog (LG_DEBUG, "graphtastical: dumping mychans");
78    
79     DICTIONARY_FOREACH (mc, mychan_t, &state, mclist)
80     {
81     fprintf (f, "\"%s\"", mc->name);
82    
83     if (!root)
84     fprintf (f, "-- \"%s\"", pmc->name);
85    
86     pmc = mc;
87    
88     fprintf (f, "[fontsize=10]\n");
89    
90     LIST_FOREACH (n, mc->chanacs.head)
91     {
92     ca = (chanacs_t *) n->data;
93    
94     if (ca->level & CA_AKICK)
95     continue;
96    
97     fprintf (f, "\"%s\" -- \"%s\" [fontsize=10]\n", ca->myuser ? ca->myuser->name : ca->host, mc->name);
98     }
99     }
100    
101     fprintf (f, "}\n");
102    
103     was_errored = ferror (f);
104     was_errored |= fclose (f);
105     if (was_errored)
106     {
107     errno1 = errno;
108     slog (LG_ERROR, "graphtastical: cannot write to channels.dot.new: %s", strerror (errno1));
109     return;
110     }
111    
112     /* now, replace the old database with the new one, using an atomic rename */
113     unlink (DATADIR "/channels.dot");
114    
115     if ((rename (DATADIR "/channels.dot.new", DATADIR "/channels.dot")) < 0)
116     {
117     errno1 = errno;
118     slog (LG_ERROR, "graphtastical: cannot rename channels.dot.new to channels.dot: %s", strerror (errno1));
119     return;
120     }
121     }
122    
123     void
124     _modinit (module_t *m)
125     {
126     write_channels_dot_file (NULL);
127    
128     event_add ("write_channels_dot_file", write_channels_dot_file, NULL, 60);
129     }
130    
131     void
132     _moddeinit (void)
133     {
134     event_delete (write_channels_dot_file, NULL);
135     }
136    
137     /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
138     * vim:ts=8
139     * vim:sw=8
140     * vim:noexpandtab
141     */