<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf8">
<title>/usr/web/sources/contrib/fhs/threads.c - Plan 9 from Bell Labs</title>
<!-- THIS FILE IS AUTOMATICALLY GENERATED. -->
<!-- EDIT sources.tr INSTEAD. -->
</meta>
</head>
<body>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>&rsquo;s /usr/web/sources/contrib/fhs/threads.c</span></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
Copyright © 2009 Alcatel-Lucent.<br />
Distributed under the
<a href="/plan9/license.html">Lucent Public License version 1.02</a>.
<br />
<a href="/plan9/download.html">Download the Plan 9 distribution.</a>
</font>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<table width="100%" cellspacing=0 border=0><tr><td align="center">
<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left">
<pre>
<!-- END HEADER -->
#include &lt;u.h&gt;
#include &lt;libc.h&gt;
#include &lt;bio.h&gt;
#include &lt;ctype.h&gt;

char *mntpt = "/mail/fs/mbox";

typedef struct Mesg Mesg;
struct Mesg {
       char*   num;
       char*   id;             /* Message-ID */
       char*   parentid;
       int             nkids;
       Mesg**  kids;
};

Mesg*   msgs;
long    nmsgs;
Mesg**  threads;
long    nthreads;

void*
emalloc(uint n)
{
       void *p;

       p = malloc(n);
       if(p == nil)
               sysfatal("can't malloc: %r");
       memset(p, 0, n);
       setmalloctag(p, getcallerpc(&amp;n));
       return p;
}

void*
erealloc(void *p, uint n)
{
       p = realloc(p, n);
       if(p == nil)
               sysfatal("can't realloc: %r");
       setmalloctag(p, getcallerpc(&amp;n));
       return p;
}

char*
estrdup(char *s)
{
       char *t;

       t = emalloc(strlen(s)+1);
       strcpy(t, s);
       return t;
}

char*
digest(char *id)
{
       char *s, *d;

       s = nil;
       d = strchr(id, '&lt;');
       if(d){
               s = strchr(++d, '&gt;');
               if(s)
                       *s = 0;
       }
       if(d == nil || s == nil)
               d = id;
       return d;
}

char*
field(char *num, char *left)
{
       char path[32], buf[8192];
       char *right;
       int fd, n;

       snprint(path, sizeof path, "%s/%s/%s", mntpt, num, left);
       fd = open(path, OREAD);
       if(fd &lt; 0)
               sysfatal("opening file %s: %r", path);
       n = read(fd, buf, sizeof buf);
       if(n &lt; 0)
               sysfatal("reading %s: %r", path);
       buf[n] = 0;
       right = estrdup(buf);
       close(fd);
       return right;
}

Mesg*
newmsg(Mesg *m, char *num)
{
       char *s, *t, *q;
       Biobuf *b;
       char hp[100];

       m-&gt;num = estrdup(num);
       s = field(num, "messageid");
       m-&gt;id = estrdup(digest(s));
       free(s);
       s = field(num, "inreplyto");
       m-&gt;parentid = estrdup(digest(s));
       free(s);
       /*
        * If In-Reply-To doesn't exist, try References. The last
        * &lt;...&gt; part is the parent id.
        */
       if(m-&gt;parentid[0] == 0){
               snprint(hp, sizeof hp, "%s/%s/rawheader", mntpt, num);
               b = Bopen(hp, OREAD);
               if(b == nil)
                       sysfatal("Bopen %s: %r", hp);
               while((s = Brdline(b, '\n')) != nil){
                       s[Blinelen(b)-1] = 0;
                       if(strncmp(s, "References:", 11) != 0)
                               continue;
                       t = strrchr(s, '&lt;');
                       if(t == nil)
                               break;
                       t++;
                       q = strchr(t, '&gt;');
                       if(q == nil)
                               break;
                       *q = 0;
                       free(m-&gt;parentid);
                       m-&gt;parentid = estrdup(t);
               }
               Bterm(b);
       }
       m-&gt;kids = nil;
       m-&gt;nkids = 0;
       return m;
}

void
cleanup(void)
{
       int i;

       for(i = 0; i &lt; nmsgs; i++){
               free(msgs[i].num);
               free(msgs[i].id);
               free(msgs[i].parentid);
               free(msgs[i].kids);
       }
       free(msgs);
       free(threads);
}

Mesg*
findparent(Mesg *c)
{
       int i;
       char *pid, *mid;
       Mesg *m, *p;

       p = nil;
       pid = c-&gt;parentid;
       for(i = 0; i &lt; nmsgs; i++){
               m = &amp;msgs[i];
               mid = m-&gt;id;
               if(c != m &amp;&amp; strcmp(mid, pid) == 0){
                       p = m;
                       p-&gt;kids = erealloc(p-&gt;kids, (p-&gt;nkids+1)*sizeof(Mesg*));
                       p-&gt;kids[p-&gt;nkids++] = c;
                       break;
               }
       }
       return p;
}

void
printthreads(Mesg **ms, int len, int depth)
{
       int i;
       char *subj, *from, ind[100];

       strcpy(ind, "");
       if(depth &lt; nelem(ind)-1){
               memset(ind, '\t', depth);
               ind[depth] = 0;
       }
       for(i = 0; i &lt; len; i++){
               subj = field(ms[i]-&gt;num, "subject");
               from = field(ms[i]-&gt;num, "from");
               if(depth == 0)
                       print("%s%s/ %s %s\n", ind, ms[i]-&gt;num, from, subj);
               else
                       print("%s%s/ %s\n", ind, ms[i]-&gt;num, from);
               printthreads(ms[i]-&gt;kids, ms[i]-&gt;nkids, depth+1);
       }
}

void
usage(void)
{
       fprint(2, "usage: upas/threads [upasmntpt]\n");
       exits("usage");
}

void
main(int argc, char *argv[])
{
       int fd;
       long i, n;
       Dir *ms;
       Mesg *p;

       ARGBEGIN {
       default:
               usage();
       } ARGEND

       if(argc &gt; 0)
               mntpt = argv[0];
       fd = open(mntpt, OREAD);
       if(fd &lt; 0)
               sysfatal("opening %s: %r", mntpt);
       n = dirreadall(fd, &amp;ms);
       msgs = emalloc(n*sizeof(Mesg));
       for(i = 0; i &lt; n; i++)
               if(isdigit(ms[i].name[0])){
                       newmsg(&amp;msgs[nmsgs], ms[i].name);
                       nmsgs++;
               }
       close(fd);

       /* nthreads &lt;= nmesg */
       threads = emalloc(nmsgs*sizeof(Mesg*));
       for(i = 0; i &lt; nmsgs; i++){
               p = findparent(&amp;msgs[i]);
               if(p == nil)
                       threads[nthreads++] = &amp;msgs[i];
       }
       printthreads(threads, nthreads, 0);
       cleanup();

       exits(nil);
}
<!-- BEGIN TAIL -->
</pre>
</td></tr></table>
</td></tr></table>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"></span></p>
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
<center><table border="0"><tr>
<td valign="middle"><a href="http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" />
</a></td>
<td valign="middle"><a href="http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" />
</a></td>
<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" />
</td>
</tr></table></center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center>
<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
<span style="font-size: 10pt"><a href="http://www.lucent.com/copyright.html">Copyright</a></span>
<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span>
<span style="font-size: 10pt">All Rights Reserved.</span>
<br />
<span style="font-size: 10pt">Comments to</span>
<span style="font-size: 10pt"><a href="mailto:[email protected]">[email protected]</a>.</span>
</font></center>
</body>
</html>