1 /*
2  * MC account storage backend inspector
3  *
4  * Copyright © 2010 Nokia Corporation
5  * Copyright © 2010 Collabora Ltd.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include "config.h"
23 
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <glib.h>
28 #include <glib-object.h>
29 
30 #include "account-store-default.h"
31 
32 #define DOCSTRING_A \
33   "%s OP BACKEND ACCOUNT [KEY [VALUE]]\n\n"        \
34   "  OP      := <get | set | del | has | list>\n"  \
35   "  BACKEND := <"
36 
37 #define DOCSTRING_B \
38   ">\n"                                                                   \
39   "  ACCOUNT := <MANAGER>/<PROTOCOL>/<ACCOUNT-UID>\n"                    \
40   "  KEY     := <manager | protocol | DisplayName | param-<PARAMETER>>\n" \
41   "  VALUE   := <STRING>\n\n"
42 
43 #if ENABLE_LIBACCOUNTS_SSO
44 #include "account-store-libaccounts.h"
45 #endif
46 
47 typedef struct {
48   const gchar *name;
49   gchar *  (*get) (const gchar *account, const gchar *key);
50   gboolean (*set) (const gchar *account, const gchar *key, const gchar *value);
51   gboolean (*delete) (const gchar *account);
52   gboolean (*exists) (const gchar *account);
53   GStrv    (*list) (void);
54 } Backend;
55 
56 typedef enum {
57   OP_UNKNOWN,
58   OP_GET,
59   OP_SET,
60   OP_DELETE,
61   OP_EXISTS,
62   OP_LIST
63 } Operation;
64 
65 const Backend backends[] = {
66   { "default",
67     default_get,
68     default_set,
69     default_delete,
70     default_exists,
71     default_list },
72 
73 #if ENABLE_LIBACCOUNTS_SSO
74   { "libaccounts",
75     libaccounts_get,
76     libaccounts_set,
77     libaccounts_delete,
78     libaccounts_exists,
79     libaccounts_list },
80 #endif
81 
82   { NULL }
83 };
84 
85 static void usage (const gchar *name, const gchar *fmt,
86     ...) G_GNUC_NORETURN G_GNUC_PRINTF (2, 3);
87 
main(int argc,char ** argv)88 int main (int argc, char **argv)
89 {
90   int i;
91   const gchar *op_name = NULL;
92   const gchar *backend = NULL;
93   const gchar *account = NULL;
94   const gchar *setting = NULL;
95   const gchar *value = NULL;
96   const Backend *store = NULL;
97   Operation op = OP_UNKNOWN;
98   gchar *output = NULL;
99   gboolean success = FALSE;
100 
101   g_type_init ();
102   g_set_application_name (argv[0]);
103 
104   if (argc < 3)
105     usage (argv[0], "Not enough arguments");
106 
107   op_name = argv[1];
108   backend = argv[2];
109 
110   for (i = 0; backends[i].name != NULL; i++)
111     {
112       if (g_str_equal (backends[i].name, backend))
113         {
114           store = &backends[i];
115           break;
116         }
117     }
118 
119   if (store == NULL)
120     usage (argv[0], "No such backend %s", backend);
121 
122   if (g_str_equal (op_name, "get"))
123     op = OP_GET;
124   else if (g_str_equal (op_name, "set"))
125     op = OP_SET;
126   else if (g_str_equal (op_name, "del"))
127     op = OP_DELETE;
128   else if (g_str_equal (op_name, "has"))
129     op = OP_EXISTS;
130   else if (g_str_equal (op_name, "list"))
131     op = OP_LIST;
132 
133   switch (op)
134     {
135       case OP_SET:
136 
137         if (argc >= 6)
138           value = argv[5];
139 
140       case OP_GET:
141 
142         if (argc < 5)
143           usage (argv[0], "op '%s' requires an account and key", op_name);
144 
145         account = argv[3];
146         setting = argv[4];
147 
148         if (account == NULL || *account == '\0')
149           usage (argv[0], "op '%s' requires an account", op_name);
150 
151         if (setting == NULL || *setting == '\0')
152           usage (argv[0], "op '%s' requires a key", op_name);
153 
154         break;
155 
156       case OP_DELETE:
157       case OP_EXISTS:
158 
159         if (argc < 4)
160           usage (argv[0], "op '%s' requires an account", op_name);
161 
162         account = argv[3];
163         break;
164 
165       case OP_LIST:
166         if (argc < 3)
167           usage (argv[0], "op '%s' requires an backend", op_name);
168         break;
169 
170       case OP_UNKNOWN:
171         usage (argv[0], "Unknown operation: %s", op_name);
172     }
173 
174   /* if we got this far, we have all the args we need: */
175   switch (op)
176     {
177       GStrv list;
178 
179       case OP_GET:
180         output = store->get (account, setting);
181         success = output != NULL;
182         break;
183 
184       case OP_SET:
185         success = store->set (account, setting, value);
186         output = g_strdup_printf ("%s.%s set to '%s' in %s",
187             account, setting, value, store->name);
188         break;
189 
190       case OP_DELETE:
191         success = store->delete (account);
192         output = g_strdup_printf ("%s deleted from %s", account, store->name);
193         break;
194 
195       case OP_EXISTS:
196         success = store->exists (account);
197         if (success)
198           output = g_strdup_printf ("Exists in %s", store->name);
199         break;
200 
201       case OP_LIST:
202         list = store->list ();
203         output = g_strjoinv ("\n", list);
204         g_strfreev (list);
205         break;
206 
207       default:
208         output = g_strdup ("Unknown operation");
209     }
210 
211   if (output != NULL)
212     printf ("%s\n", output);
213 
214   g_free (output);
215 
216   return success ? 0 : 1;
217 }
218 
219 static void
usage(const gchar * name,const gchar * fmt,...)220 usage (const gchar *name, const gchar *fmt, ...)
221 {
222   guint i;
223   va_list ap;
224 
225   fprintf (stderr, DOCSTRING_A, name);
226 
227   fprintf (stderr, "%s", backends[0].name);
228 
229   for (i = 1; backends[i].name != NULL; i++)
230     fprintf (stderr, " | %s", backends[i].name);
231 
232   fprintf (stderr, DOCSTRING_B);
233 
234   va_start (ap, fmt);
235   vfprintf (stderr, fmt, ap);
236   va_end (ap);
237 
238   exit (1);
239 }
240