chiark / gitweb /
journald: fix minor memory leak
[elogind.git] / src / journal / journal-qrcode.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2012 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <stdbool.h>
27
28 #include <qrencode.h>
29
30 #include "journal-qrcode.h"
31
32 #define WHITE_ON_BLACK "\033[40;37;1m"
33 #define NORMAL "\033[0m"
34
35 static void print_border(FILE *output, unsigned width) {
36         unsigned x, y;
37
38         /* Four rows of border */
39         for (y = 0; y < 4; y += 2) {
40                 fputs(WHITE_ON_BLACK, output);
41
42                 for (x = 0; x < 4 + width + 4; x++)
43                         fputs("\342\226\210", output);
44
45                 fputs(NORMAL "\n", output);
46         }
47 }
48
49 int print_qr_code(
50                 FILE *output,
51                 const void *seed,
52                 size_t seed_size,
53                 uint64_t start,
54                 uint64_t interval,
55                 const char *hn,
56                 sd_id128_t machine) {
57
58         FILE *f;
59         char *url = NULL;
60         size_t url_size = 0, i;
61         QRcode* qr;
62         unsigned x, y;
63
64         assert(seed);
65         assert(seed_size > 0);
66
67         f = open_memstream(&url, &url_size);
68         if (!f)
69                 return -ENOMEM;
70
71         fputs("fss://", f);
72
73         for (i = 0; i < seed_size; i++) {
74                 if (i > 0 && i % 3 == 0)
75                         fputc('-', f);
76                 fprintf(f, "%02x", ((uint8_t*) seed)[i]);
77         }
78
79         fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR,
80                 start,
81                 interval,
82                 SD_ID128_FORMAT_VAL(machine));
83
84         if (hn)
85                 fprintf(f, ";hostname=%s", hn);
86
87         if (ferror(f)) {
88                 fclose(f);
89                 free(url);
90                 return -ENOMEM;
91         }
92
93         fclose(f);
94
95         qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
96         free(url);
97
98         if (!qr)
99                 return -ENOMEM;
100
101         print_border(output, qr->width);
102
103         for (y = 0; y < (unsigned) qr->width; y += 2) {
104                 const uint8_t *row1, *row2;
105
106                 row1 = qr->data + qr->width * y;
107                 row2 = row1 + qr->width;
108
109                 fputs(WHITE_ON_BLACK, output);
110                 for (x = 0; x < 4; x++)
111                         fputs("\342\226\210", output);
112
113                 for (x = 0; x < (unsigned) qr->width; x ++) {
114                         bool a, b;
115
116                         a = row1[x] & 1;
117                         b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false;
118
119                         if (a && b)
120                                 fputc(' ', output);
121                         else if (a)
122                                 fputs("\342\226\204", output);
123                         else if (b)
124                                 fputs("\342\226\200", output);
125                         else
126                                 fputs("\342\226\210", output);
127                 }
128
129                 for (x = 0; x < 4; x++)
130                         fputs("\342\226\210", output);
131                 fputs(NORMAL "\n", output);
132         }
133
134         print_border(output, qr->width);
135
136         QRcode_free(qr);
137         return 0;
138 }