741dfa9f05f8e450808f8135fe9f7ac995b5f987
[sharpe/samba-autobuild/.git] / source3 / utils / net_cache.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) Rafal Szczesniak    2002
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19  
20
21 #include "includes.h"
22 #include "net.h"
23
24 /**
25  * @file net_cache.c
26  * @brief This is part of the net tool which is basically command
27  *        line wrapper for gencache.c functions (mainly for testing)
28  *
29  **/
30
31
32 /*
33  * These routines are used via gencache_iterate() to display the cache's contents
34  * (print_cache_entry) and to flush it (delete_cache_entry).
35  * Both of them are defined by first arg of gencache_iterate() routine.
36  */
37 static void print_cache_entry(const char* keystr, const char* datastr,
38                               const time_t timeout, void* dptr)
39 {
40         char *timeout_str;
41         char *alloc_str = NULL;
42         time_t now_t = time(NULL);
43         struct tm timeout_tm, *now_tm;
44         /* localtime returns statically allocated pointer, so timeout_tm
45            has to be copied somewhere else */
46
47         now_tm = localtime(&timeout);
48         if (!now_tm) {
49                 return;
50         }
51         memcpy(&timeout_tm, now_tm, sizeof(struct tm));
52         now_tm = localtime(&now_t);
53         if (!now_tm) {
54                 return;
55         }
56
57         /* form up timeout string depending whether it's today's date or not */
58         if (timeout_tm.tm_year != now_tm->tm_year ||
59                         timeout_tm.tm_mon != now_tm->tm_mon ||
60                         timeout_tm.tm_mday != now_tm->tm_mday) {
61             
62                 timeout_str = asctime(&timeout_tm);
63                 if (!timeout_str) {
64                         return;
65                 }       
66                 timeout_str[strlen(timeout_str) - 1] = '\0';    /* remove tailing CR */
67         } else {
68                 asprintf(&alloc_str, "%.2d:%.2d:%.2d", timeout_tm.tm_hour,
69                          timeout_tm.tm_min, timeout_tm.tm_sec);
70                 if (!alloc_str) {
71                         return;
72                 }
73                 timeout_str = alloc_str;
74         }
75         
76         d_printf("Key: %s\t Timeout: %s\t Value: %s  %s\n", keystr,
77                  timeout_str, datastr, timeout > now_t ? "": "(expired)");
78
79         SAFE_FREE(alloc_str);
80 }
81
82 static void delete_cache_entry(const char* keystr, const char* datastr,
83                                const time_t timeout, void* dptr)
84 {
85         if (!gencache_del(keystr))
86                 d_fprintf(stderr, "Couldn't delete entry! key = %s\n", keystr);
87 }
88
89
90 /**
91  * Parse text representation of timeout value
92  *
93  * @param timeout_str string containing text representation of the timeout
94  * @return numeric timeout of time_t type
95  **/
96 static time_t parse_timeout(const char* timeout_str)
97 {
98         char sign = '\0', *number = NULL, unit = '\0';
99         int len, number_begin, number_end;
100         time_t timeout;
101
102         /* sign detection */
103         if (timeout_str[0] == '!' || timeout_str[0] == '+') {
104                 sign = timeout_str[0];
105                 number_begin = 1;
106         } else {
107                 number_begin = 0;
108         }
109         
110         /* unit detection */
111         len = strlen(timeout_str);
112         switch (timeout_str[len - 1]) {
113         case 's':
114         case 'm':
115         case 'h':
116         case 'd':
117         case 'w': unit = timeout_str[len - 1];
118         }
119         
120         /* number detection */
121         len = (sign) ? strlen(&timeout_str[number_begin]) : len;
122         number_end = (unit) ? len - 1 : len;
123         number = SMB_STRNDUP(&timeout_str[number_begin], number_end);
124         
125         /* calculate actual timeout value */
126         timeout = (time_t)atoi(number);
127
128         switch (unit) {
129         case 'm': timeout *= 60; break;
130         case 'h': timeout *= 60*60; break;
131         case 'd': timeout *= 60*60*24; break;
132         case 'w': timeout *= 60*60*24*7; break;  /* that's fair enough, I think :) */
133         }
134         
135         switch (sign) {
136         case '!': timeout = time(NULL) - timeout; break;
137         case '+':
138         default:  timeout += time(NULL); break;
139         }
140         
141         if (number) SAFE_FREE(number);
142         return timeout; 
143 }
144
145
146 /**
147  * Add an entry to the cache. If it does exist, then set it.
148  * 
149  * @param argv key, value and timeout are passed in command line
150  * @return 0 on success, otherwise failure
151  **/
152 static int net_cache_add(int argc, const char **argv)
153 {
154         const char *keystr, *datastr, *timeout_str;
155         time_t timeout;
156         
157         if (argc < 3) {
158                 d_printf("\nUsage: net cache add <key string> <data string> <timeout>\n");
159                 return -1;
160         }
161         
162         keystr = argv[0];
163         datastr = argv[1];
164         timeout_str = argv[2];
165         
166         /* parse timeout given in command line */
167         timeout = parse_timeout(timeout_str);
168         if (!timeout) {
169                 d_fprintf(stderr, "Invalid timeout argument.\n");
170                 return -1;
171         }
172         
173         if (gencache_set(keystr, datastr, timeout)) {
174                 d_printf("New cache entry stored successfully.\n");
175                 gencache_shutdown();
176                 return 0;
177         }
178         
179         d_fprintf(stderr, "Entry couldn't be added. Perhaps there's already such a key.\n");
180         gencache_shutdown();
181         return -1;
182 }
183
184 /**
185  * Delete an entry in the cache
186  * 
187  * @param argv key to delete an entry of
188  * @return 0 on success, otherwise failure
189  **/
190 static int net_cache_del(int argc, const char **argv)
191 {
192         const char *keystr = argv[0];
193         
194         if (argc < 1) {
195                 d_printf("\nUsage: net cache del <key string>\n");
196                 return -1;
197         }
198         
199         if(gencache_del(keystr)) {
200                 d_printf("Entry deleted.\n");
201                 return 0;
202         }
203
204         d_fprintf(stderr, "Couldn't delete specified entry\n");
205         return -1;
206 }
207
208
209 /**
210  * Get and display an entry from the cache
211  * 
212  * @param argv key to search an entry of
213  * @return 0 on success, otherwise failure
214  **/
215 static int net_cache_get(int argc, const char **argv)
216 {
217         const char* keystr = argv[0];
218         char* valuestr;
219         time_t timeout;
220
221         if (argc < 1) {
222                 d_printf("\nUsage: net cache get <key>\n");
223                 return -1;
224         }
225         
226         if (gencache_get(keystr, &valuestr, &timeout)) {
227                 print_cache_entry(keystr, valuestr, timeout, NULL);
228                 return 0;
229         }
230
231         d_fprintf(stderr, "Failed to find entry\n");
232         return -1;
233 }
234
235
236 /**
237  * Search an entry/entries in the cache
238  * 
239  * @param argv key pattern to match the entries to
240  * @return 0 on success, otherwise failure
241  **/
242 static int net_cache_search(int argc, const char **argv)
243 {
244         const char* pattern;
245         
246         if (argc < 1) {
247                 d_printf("Usage: net cache search <pattern>\n");
248                 return -1;
249         }
250         
251         pattern = argv[0];
252         gencache_iterate(print_cache_entry, NULL, pattern);
253         return 0;
254 }
255
256
257 /**
258  * List the contents of the cache
259  * 
260  * @param argv ignored in this functionailty
261  * @return always returns 0
262  **/
263 static int net_cache_list(int argc, const char **argv)
264 {
265         const char* pattern = "*";
266         gencache_iterate(print_cache_entry, NULL, pattern);
267         gencache_shutdown();
268         return 0;
269 }
270
271
272 /**
273  * Flush the whole cache
274  * 
275  * @param argv ignored in this functionality
276  * @return always returns 0
277  **/
278 static int net_cache_flush(int argc, const char **argv)
279 {
280         const char* pattern = "*";
281         gencache_iterate(delete_cache_entry, NULL, pattern);
282         gencache_shutdown();
283         return 0;
284 }
285
286
287 /**
288  * Short help
289  *
290  * @param argv ignored in this functionality
291  * @return always returns -1
292  **/
293 static int net_cache_usage(int argc, const char **argv)
294 {
295         d_printf("  net cache add \t add add new cache entry\n");
296         d_printf("  net cache del \t delete existing cache entry by key\n");
297         d_printf("  net cache flush \t delete all entries existing in the cache\n");
298         d_printf("  net cache get \t get cache entry by key\n");
299         d_printf("  net cache search \t search for entries in the cache, by given pattern\n");
300         d_printf("  net cache list \t list all cache entries (just like search for \"*\")\n");
301         return -1;
302 }
303
304
305 /**
306  * Entry point to 'net cache' subfunctionality
307  *
308  * @param argv arguments passed to further called functions
309  * @return whatever further functions return
310  **/
311 int net_cache(int argc, const char **argv)
312 {
313         struct functable func[] = {
314                 {"add", net_cache_add},
315                 {"del", net_cache_del},
316                 {"get", net_cache_get},
317                 {"search", net_cache_search},
318                 {"list", net_cache_list},
319                 {"flush", net_cache_flush},
320                 {NULL, NULL}
321         };
322
323         return net_run_function(argc, argv, func, net_cache_usage);
324 }