Tizen 2.1 base
[platform/upstream/hplip.git] / io / hpmud / hp-mkuri.c
1 /*****************************************************************************\
2
3   hp-mkuri.c - make uri with multi-point transport driver (HPMUD)
4  
5   (c) 2008-2009 Copyright Hewlett-Packard Development Company, LP
6
7   Permission is hereby granted, free of charge, to any person obtaining a copy 
8   of this software and associated documentation files (the "Software"), to deal 
9   in the Software without restriction, including without limitation the rights 
10   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
11   of the Software, and to permit persons to whom the Software is furnished to do 
12   so, subject to the following conditions:
13
14   The above copyright notice and this permission notice shall be included in all
15   copies or substantial portions of the Software.
16
17   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
18   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
19   FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
20   COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
21   IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
22   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 \*****************************************************************************/
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <dirent.h>
30 #include <signal.h>
31 #include <ctype.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <syslog.h>
36 #include <dlfcn.h>
37 #include "hpmud.h"
38
39 #define _STRINGIZE(x) #x
40 #define STRINGIZE(x) _STRINGIZE(x)
41 //#define BUG(args...) fprintf(stderr, __FILE__ " " STRINGIZE(__LINE__) ": " args)
42 #define BUG(args...) syslog(LOG_ERR, __FILE__ " " STRINGIZE(__LINE__) ": " args)
43
44 static int verbose;
45 static char homedir[255] = "";
46
47 static void usage()
48 {
49    fprintf(stdout, "HPLIP Make URI %s\n", VERSION);
50    fprintf(stdout, "(c) 2008 Copyright Hewlett-Packard Development Company, LP\n");
51    fprintf(stdout, "usage: hp-mkuri -i ip [-p port]\n");
52    fprintf(stdout, "usage: hp-mkuri -z hostname\n");
53    fprintf(stdout, "usage: hp-mkuri -b busnum -d devnum\n");
54    fprintf(stdout, "usage: hp-mkuri -s serialnum\n");
55    fprintf(stdout, "usage: hp-mkuri -l /dev/parportx\n");
56    fprintf(stdout, "usage: hp-mkuri -m hostname [-p port]\n");
57    fprintf(stdout, "usage: hp-mkuri -o (probe)\n");
58    fprintf(stdout, "usage: hp-mkuri -c [-n (no notifier)] (check support)\n");
59    fprintf(stdout, "\nSupport matrix:\n");
60    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
61    fprintf(stdout, "| return value | printer | fax | plugin_required | plugin_optional |\n");
62    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
63    fprintf(stdout, "|       0      |   yes   |     |                 |                 |\n");
64    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
65    fprintf(stdout, "|       1      |    *    |  *  |        *        |        *        |\n");
66    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
67    fprintf(stdout, "|       2      |   yes   |     |       yes       |                 |\n");
68    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
69    fprintf(stdout, "|       3      |   yes   |     |                 |       yes       |\n");
70    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
71    fprintf(stdout, "|       4      |   yes   | yes |                 |                 |\n");
72    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
73    fprintf(stdout, "|       5      |   yes   | yes |       yes       |                 |\n");
74    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
75    fprintf(stdout, "|       6      |   yes   | yes |                 |       yes       |\n");
76    fprintf(stdout, "+--------------+---------+-----+-----------------+-----------------+\n");
77    fprintf(stdout, "    * no support or error\n");
78 } /* usage */
79
80 static int GetPair(char *buf, int buf_len, char *key, char *value, char **tail)
81 {
82    int i=0, j;
83
84    key[0] = 0;
85    value[0] = 0;
86
87    if (buf[i] == '#')
88    {
89       for (; buf[i] != '\n' && i < buf_len; i++);  /* eat comment line */
90       if (buf[i] == '\n')
91          i++;   /* bump past '\n' */
92    }
93
94    j = 0;
95    while ((buf[i] != '=') && (i < buf_len) && (j < HPMUD_LINE_SIZE))
96       key[j++] = buf[i++];
97    for (j--; key[j] == ' ' && j > 0; j--);  /* eat white space before = */
98    key[++j] = 0;
99
100    if (buf[i] == '=')
101       for (i++; buf[i] == ' ' && i < buf_len; i++);  /* eat white space after = */
102
103    j = 0;
104    while ((buf[i] != '\n') && (i < buf_len) && (j < HPMUD_LINE_SIZE))
105       value[j++] = buf[i++];
106    for (j--; value[j] == ' ' && j > 0; j--);  /* eat white space before \n */
107    value[++j] = 0;
108
109    if (buf[i] == '\n')
110      i++;   /* bump past '\n' */
111
112    if (tail != NULL)
113       *tail = buf + i;  /* tail points to next line */
114
115    return i;
116 }
117
118 static int ReadConfig()
119 {
120    char key[HPMUD_LINE_SIZE];
121    char value[HPMUD_LINE_SIZE];
122    char rcbuf[255];
123    char section[32];
124    char *tail;
125    FILE *inFile = NULL;
126    int stat=1;
127
128    homedir[0] = 0;
129         
130    if((inFile = fopen(CONFDIR "/hplip.conf", "r")) == NULL) 
131    {
132       BUG("unable to open %s: %m\n", CONFDIR "/hplip.conf");
133       goto bugout;
134    } 
135
136    section[0] = 0;
137
138    /* Read the config file */
139    while ((fgets(rcbuf, sizeof(rcbuf), inFile) != NULL))
140    {
141       if (rcbuf[0] == '[')
142       {
143          strncpy(section, rcbuf, sizeof(section)); /* found new section */
144          continue;
145       }
146
147       GetPair(rcbuf, strlen(rcbuf), key, value, &tail);
148
149       if ((strncasecmp(section, "[dirs]", 6) == 0) && (strcasecmp(key, "home") == 0))
150       {
151          strncpy(homedir, value, sizeof(homedir));
152          break;  /* done */
153       }
154    }
155         
156    stat = 0;
157
158 bugout:        
159    if (inFile != NULL)
160       fclose(inFile);
161          
162    return stat;
163 }
164
165 static int generalize_model(const char *sz, char *buf, int bufSize)
166 {
167    const char *pMd=sz;
168    int i, j, dd=0;
169
170    for (i=0; pMd[i] == ' ' && i < bufSize; i++);  /* eat leading white space */
171
172    for (j=0; (pMd[i] != 0) && (pMd[i] != ';') && (j < bufSize); i++)
173    {
174       if (pMd[i]==' ' || pMd[i]=='/')
175       {
176          /* Remove double spaces. */
177          if (!dd)
178          { 
179             buf[j++] = '_';   /* convert space to "_" */
180             dd=1;              
181          }
182       }
183       else
184       {
185          buf[j++] = tolower(pMd[i]);
186          dd=0;       
187       }
188    }
189
190    for (j--; buf[j] == '_' && j > 0; j--);  /* eat trailing white space */
191
192    buf[++j] = 0;
193
194    return j;   /* length does not include zero termination */
195 }
196
197 static int set_x_environment(void)
198 {
199    DIR *dir=NULL;
200    FILE *file=NULL;
201    struct dirent *entry;
202    char path[32], line[256], cookie[128], *p;
203    int i, c, stat=1;
204
205    if ((dir = opendir("/proc"))==NULL)
206    {
207       BUG("unable to open /proc: %m\n");
208       goto bugout;
209    }
210
211    while ((entry = readdir(dir)) != NULL) 
212    {
213       if (!isdigit(*entry->d_name))
214          continue;
215
216       /* Get command line for this PID. */
217       snprintf(path, sizeof(path), "/proc/%s/cmdline", entry->d_name);
218       if ((file = fopen(path, "r")) == NULL)
219          continue;
220       for (i=0; ((c = getc(file)) != EOF) && (i < (sizeof(line)-1)); i++)
221       {
222          if (c == 0)
223             c = ' ';
224          line[i] = c;
225       }
226       line[i]=0;
227       fclose(file);
228       if ((p = strstr(line, "-auth ")))
229       {
230          /* Found X server. */
231          for (p+=6; (*p == ' ') && (*p != 0); p++);  /* eat any white space before cookie */
232          for (i=0; (*(p+i) != ' ') && (*(p+i) != 0) && i < (sizeof(cookie)-1); i++)
233             cookie[i] = *(p+i);
234          cookie[i]=0;
235          setenv("XAUTHORITY", cookie, 1);
236          setenv("DISPLAY", ":0.0", 1);
237          break; 
238       }
239    } /* while ((entry = readdir(dir)) != NULL) */ 
240
241    stat = 0;
242
243 bugout:
244    if (dir)
245       closedir(dir);
246    return(stat);
247 }  /* set_x_environment */
248
249 static int notify(const char *summary, const char *message, int ms_timeout) 
250 {
251     void *handle=NULL, *n;
252     int stat=1; 
253
254     typedef void  (*notify_init_t)(char *);
255     typedef void *(*notify_notification_new_t)(const char *, const char *, const char *, void *);
256     typedef void  (*notify_notification_set_timeout_t)(void *, int);
257     typedef void (*notify_notification_show_t)(void *, char *);
258
259     notify_init_t n_init;
260     notify_notification_new_t n_new;
261     notify_notification_set_timeout_t n_timeout;
262     notify_notification_show_t n_show;
263
264     set_x_environment();
265
266     /* Bypass glib build dependencies by loading libnotify manually. */  
267
268     if ((handle = dlopen("libnotify.so.1", RTLD_LAZY)) == NULL)
269     {
270        BUG("failed to open libnotify: %m\n");
271        goto bugout;
272     }
273
274     if ((n_init = (notify_init_t)dlsym(handle, "notify_init")) == NULL)
275     {
276        BUG("failed to find notify_init: %m\n");
277        goto bugout; 
278     }
279     n_init("Basics");
280
281     if ((n_new = (notify_notification_new_t)dlsym(handle, "notify_notification_new")) == NULL)
282     {
283        BUG("failed to find notify_notification_new: %m\n");
284        goto bugout;
285     }
286     n = n_new(summary, message, NULL, NULL);
287
288     if ((n_timeout = (notify_notification_set_timeout_t)dlsym(handle, "notify_notification_set_timeout")) == NULL)
289     {
290         BUG("failed to find notify_notification_set_timeout: %m\n");
291         goto bugout;
292     }
293     n_timeout(n, ms_timeout);
294
295     if ((n_show = (notify_notification_show_t)dlsym(handle, "notify_notification_show")) == NULL)
296     {
297        BUG("failed to find notify_notification_show: %m\n");
298        goto bugout;
299     }
300     n_show(n, NULL);
301
302     stat=0;
303
304 bugout:
305     if (handle)
306        dlclose(handle);
307
308     return stat;
309 } /* notify */
310
311 static int check_support(int send_notify)
312 {
313    struct stat sb;
314    char model[256];
315    int ret=1, plugin_installed=1;
316    const char *pm;
317    char m[256];
318    char datfile[256];
319    char value[32];
320    int support, plugin, fax;
321
322    /* Get hp model from environment variables. */
323    if ((pm = getenv("hp_model")))
324    {
325       strncpy(model, pm, sizeof(model));
326    }
327    else
328    {
329       fprintf(stderr, "error no hp_model environment variable set\n");
330       BUG("error no hp_model environment variable set\n");
331       goto bugout;
332    }
333
334    if (model[0]==0)
335    {
336       BUG("invalid parameter(s)\n");
337       usage();
338       goto bugout;
339    } 
340
341    generalize_model(model, m, sizeof(m));
342    snprintf(model, sizeof(model), "[%s]", m);
343
344    if (ReadConfig())
345       goto bugout;
346
347    snprintf(datfile, sizeof(datfile), "%s/data/models/models.dat", homedir);
348
349    if (hpmud_get_key_value(datfile, model, "support-type", value, sizeof(value)) != HPMUD_R_OK)
350       goto bugout;
351    support = strtol(value, NULL, 10);
352    if (hpmud_get_key_value(datfile, model, "plugin", value, sizeof(value)) != HPMUD_R_OK)
353       goto bugout;
354    plugin = strtol(value, NULL, 10);
355    if (hpmud_get_key_value(datfile, model, "fax-type", value, sizeof(value)) != HPMUD_R_OK)
356       goto bugout;
357    fax = strtol(value, NULL, 10);
358
359    /* See if device is supported by hplip. */
360    if (support == HPMUD_SUPPORT_TYPE_NONE)
361    {
362       BUG("%s is not supported by HPLIP %s\n", pm, VERSION);
363       goto bugout;
364    }
365
366    if (stat("/etc/udev/rules.d/86-hpmud-hp_laserjet_1018.rules", &sb) == -1) 
367       plugin_installed=0;
368
369    if (send_notify && !plugin_installed)
370    {
371       /* See if device requires a Plugin. */
372       switch (plugin)
373       {
374          case HPMUD_PLUGIN_TYPE_REQUIRED:
375             BUG("%s requires a proprietary plugin\n", pm);
376             notify(pm, "requires a proprietary plugin, run hp-setup", 30000);
377             break;
378          case HPMUD_PLUGIN_TYPE_OPTIONAL:
379             BUG("%s has a optional proprietary plugin\n", pm);
380             notify(pm, "has a optional proprietary plugin, run hp-setup", 30000);
381             break;
382          default:
383             break;
384       }         
385    }
386
387    ret = 0;
388    if (plugin == HPMUD_PLUGIN_TYPE_REQUIRED)
389       ret = 2;
390    else if (plugin == HPMUD_PLUGIN_TYPE_OPTIONAL)
391       ret = 3;
392    if (fax > 0)
393    {
394       ret = 4;
395       if (plugin == HPMUD_PLUGIN_TYPE_REQUIRED)
396          ret = 5;
397       else if (plugin == HPMUD_PLUGIN_TYPE_OPTIONAL)
398          ret = 6;
399    }
400
401 bugout:
402    return ret;
403 } /* check_support */
404
405 int main(int argc, char *argv[])
406 {
407    char ip[HPMUD_LINE_SIZE];  /* internet address */
408    char bn[HPMUD_LINE_SIZE];  /* usb bus number */
409    char dn[HPMUD_LINE_SIZE];  /* usb device number */
410    char sn[HPMUD_LINE_SIZE];  /* usb serial number */
411    char pp[HPMUD_LINE_SIZE];  /* parallel port device */
412    char uri[HPMUD_LINE_SIZE];
413    char host[HPMUD_LINE_SIZE];
414    int i, port=1, ret=1, probe=0, support=0, send_notify=1;
415    enum HPMUD_RESULT stat;
416    char buf[HPMUD_LINE_SIZE*64];
417    int cnt, bytes_read;
418
419    ip[0] = bn[0] = dn[0] = pp[0] = uri[0] = sn[0] = host[0] = 0;
420    while ((i = getopt(argc, argv, "vhocni:p:b:d:l:s:z:")) != -1)
421    {
422       switch (i)
423       {
424       case 'i':
425          strncpy(ip, optarg, sizeof(ip));
426          break;
427       case 'z':
428          strncpy(host, optarg, sizeof(host));
429          break;
430       case 'p':
431          port = strtol(optarg, NULL, 10);
432          break;
433       case 'b':
434          strncpy(bn, optarg, sizeof(bn));
435          break;
436       case 'd':
437          strncpy(dn, optarg, sizeof(dn));
438          break;
439       case 'l':
440          strncpy(pp, optarg, sizeof(pp));
441          break;
442       case 's':
443          strncpy(sn, optarg, sizeof(sn));
444          break;
445       case 'o':
446          probe++;
447          break;
448       case 'c':
449          support++;
450          break;
451       case 'v':
452          verbose++;
453          break;
454       case 'n':
455          send_notify=0;
456          break;
457       case 'h':
458          usage();
459          exit(0);
460       case '?':
461          usage();
462          fprintf(stderr, "unknown argument: %s\n", argv[1]);
463          exit(-1);
464       default:
465          break;
466       }
467    }
468
469    if (ip[0]==0 && (!(bn[0] && dn[0])) && pp[0]==0 && probe==0 && sn[0]==0 && support==0 && host[0]==0)
470    {
471       fprintf(stderr, "invalid command parameter(s)\n");
472       usage();
473       goto bugout;
474    }   
475
476    if (probe)
477    {
478       hpmud_probe_devices(HPMUD_BUS_ALL, buf, sizeof(buf), &cnt, &bytes_read);
479       if (bytes_read)
480          fprintf(stdout, "%s", buf);
481    }
482
483 #ifdef HAVE_LIBNETSNMP
484    if (ip[0])
485    {
486       stat = hpmud_make_net_uri(ip, port, uri, sizeof(uri), &bytes_read);
487       if (stat == HPMUD_R_OK)
488       {
489          fprintf(stdout, "%s\n", uri);
490          fprintf(stdout, "hpaio%s\n", &uri[2]);
491       }
492    }
493    if (host[0])
494    {
495       stat = hpmud_make_mdns_uri(host, port, uri, sizeof(uri), &bytes_read);
496       if (stat == HPMUD_R_OK)
497       {
498          fprintf(stdout, "%s\n", uri);
499          fprintf(stdout, "hpaio%s\n", &uri[2]);
500       }
501    }
502 #endif
503
504    if (bn[0] && dn[0])
505    {
506       stat = hpmud_make_usb_uri(bn, dn, uri, sizeof(uri), &bytes_read);
507       if (stat == HPMUD_R_OK)
508       {
509          fprintf(stdout, "%s\n", uri);
510          fprintf(stdout, "hpaio%s\n", &uri[2]);
511       }
512    }
513
514    if (sn[0])
515    {
516       stat = hpmud_make_usb_serial_uri(sn, uri, sizeof(uri), &bytes_read);
517       if (stat == HPMUD_R_OK)
518       {
519          fprintf(stdout, "%s\n", uri);
520          fprintf(stdout, "hpaio%s\n", &uri[2]);
521       }
522    }
523
524 #ifdef HAVE_PPORT
525    if (pp[0])
526    {
527       stat = hpmud_make_par_uri(pp, uri, sizeof(uri), &bytes_read);
528       if (stat == HPMUD_R_OK)
529       {
530          fprintf(stdout, "%s\n", uri);
531          fprintf(stdout, "hpaio%s\n", &uri[2]);
532       }
533    }
534 #endif
535
536    ret = 0;
537
538    if (support)
539       ret = check_support(send_notify);
540
541 bugout:
542    exit(ret);
543 } /* main */