123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- #include <sys/types.h>
- #include <stdio.h>
- #include <string.h>
- #include <time.h>
- #include "util.h"
- static struct tm tmnow;
- static time_t now;
- static char *line;
- static size_t linesize;
- static void
- printcontent(const char *s)
- {
- for (; *s; ++s) {
- switch (*s) {
- case '<': fputs("<", stdout); break;
- case '>': fputs(">", stdout); break;
- case '\'': fputs("'", stdout); break;
- case '&': fputs("&", stdout); break;
- case '"': fputs(""", stdout); break;
- case '\\':
- s++;
- switch (*s) {
- case 'n': putchar('\n'); break;
- case '\\': putchar('\\'); break;
- case 't': putchar('\t'); break;
- }
- break;
- default: putchar(*s);
- }
- }
- }
- static void
- printfeed(FILE *fp, const char *feedname)
- {
- char *fields[FieldLast], *p, *tmp;
- struct tm parsedtm, *tm;
- time_t parsedtime;
- ssize_t linelen;
- int c;
- while ((linelen = getline(&line, &linesize, fp)) > 0 &&
- !ferror(stdout)) {
- if (line[linelen - 1] == '\n')
- line[--linelen] = '\0';
- parseline(line, fields);
- fputs("<entry>\n\t<title>", stdout);
- if (feedname[0]) {
- fputs("[", stdout);
- xmlencode(feedname, stdout);
- fputs("] ", stdout);
- }
- xmlencode(fields[FieldTitle], stdout);
- fputs("</title>\n", stdout);
- if (fields[FieldLink][0]) {
- fputs("\t<link rel=\"alternate\" href=\"", stdout);
- xmlencode(fields[FieldLink], stdout);
- fputs("\" />\n", stdout);
- }
- /* prefer link over id for Atom <id>. */
- fputs("\t<id>", stdout);
- if (fields[FieldLink][0])
- xmlencode(fields[FieldLink], stdout);
- else if (fields[FieldId][0])
- xmlencode(fields[FieldId], stdout);
- fputs("</id>\n", stdout);
- if (fields[FieldEnclosure][0]) {
- fputs("\t<link rel=\"enclosure\" href=\"", stdout);
- xmlencode(fields[FieldEnclosure], stdout);
- fputs("\" />\n", stdout);
- }
- parsedtime = 0;
- if (strtotime(fields[FieldUnixTimestamp], &parsedtime) ||
- !(tm = gmtime_r(&parsedtime, &parsedtm)))
- tm = &tmnow;
- fprintf(stdout, "\t<updated>%04d-%02d-%02dT%02d:%02d:%02dZ</updated>\n",
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- if (fields[FieldAuthor][0]) {
- fputs("\t<author><name>", stdout);
- xmlencode(fields[FieldAuthor], stdout);
- fputs("</name></author>\n", stdout);
- }
- if (fields[FieldContent][0]) {
- if (!strcmp(fields[FieldContentType], "html")) {
- fputs("\t<content type=\"html\">", stdout);
- } else {
- /* NOTE: an RSS/Atom viewer may or may not format
- whitespace such as newlines.
- Workaround: type="html" and <![CDATA[<pre></pre>]]> */
- fputs("\t<content type=\"text\">", stdout);
- }
- printcontent(fields[FieldContent]);
- fputs("</content>\n", stdout);
- }
- for (p = fields[FieldCategory]; (tmp = strchr(p, '|')); p = tmp + 1) {
- c = *tmp;
- *tmp = '\0'; /* temporary NUL-terminate */
- if (*p) {
- fputs("\t<category term=\"", stdout);
- xmlencode(p, stdout);
- fputs("\" />\n", stdout);
- }
- *tmp = c; /* restore */
- }
- fputs("</entry>\n", stdout);
- }
- }
- int
- main(int argc, char *argv[])
- {
- struct tm *tm;
- FILE *fp;
- char *name;
- int i;
- if (pledge(argc == 1 ? "stdio" : "stdio rpath", NULL) == -1)
- err(1, "pledge");
- if ((now = time(NULL)) == (time_t)-1)
- errx(1, "time");
- if (!(tm = gmtime_r(&now, &tmnow)))
- err(1, "gmtime_r");
- fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"
- "\t<title type=\"text\">Newsfeed</title>\n"
- "\t<author><name>sfeed</name></author>\n", stdout);
- printf("\t<id>urn:newsfeed:%lld</id>\n"
- "\t<updated>%04d-%02d-%02dT%02d:%02d:%02dZ</updated>\n",
- (long long)now,
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- if (argc == 1) {
- printfeed(stdin, "");
- checkfileerror(stdin, "<stdin>", 'r');
- } else {
- for (i = 1; i < argc; i++) {
- if (!(fp = fopen(argv[i], "r")))
- err(1, "fopen: %s", argv[i]);
- name = ((name = strrchr(argv[i], '/'))) ? name + 1 : argv[i];
- printfeed(fp, name);
- checkfileerror(fp, argv[i], 'r');
- checkfileerror(stdout, "<stdout>", 'w');
- fclose(fp);
- }
- }
- fputs("</feed>\n", stdout);
- checkfileerror(stdout, "<stdout>", 'w');
- return 0;
- }
|