2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
29 #include <sys/types.h>
36 #include "pwmd-error.h"
38 #include "util-misc.h"
39 #include "util-string.h"
44 void log_write (const char *fmt
, ...);
47 valid_filename (const char *filename
)
51 if (!filename
|| !*filename
)
54 if (filename
[0] == '-' && filename
[1] == 0)
57 for (p
= filename
; *p
; p
++)
59 if (*p
== '/' || isspace (*p
))
66 /* If 'user' is null then lookup entry for 'uid'. Caller must free 'buf'. */
68 get_pwd_struct (const char *user
, uid_t uid
, struct passwd
*pw
, char **buf
,
71 struct passwd
*result
= NULL
;
72 #ifdef HAVE_GETPWNAM_R
76 len
= sysconf (_SC_GETPW_R_SIZE_MAX
);
85 err
= getpwnam_r (user
, pw
, *buf
, len
, &result
);
87 err
= getpwuid_r (uid
, pw
, *buf
, len
, &result
);
95 *rc
= gpg_error_from_errno (err
);
103 result
= getpwnam (user
);
105 result
= getpwuid (uid
);
108 *rc
= gpg_error_from_syserror ();
115 get_pwd_entry(uid_t uid
, int which
)
120 struct passwd
*result
= get_pwd_struct (NULL
, uid
, &pw
, &buf
, &rc
);
129 value
= str_dup (result
->pw_dir
);
131 value
= str_dup (result
->pw_name
);
139 get_username (uid_t uid
)
141 return get_pwd_entry (uid
, 1);
148 return home_directory
;
150 home_directory
= get_pwd_entry (getuid(), 0);
151 return home_directory
;
155 expand_homedir (char *str
)
161 char *dir
= get_pwd_entry(getuid(), 0);
167 s
= str_asprintf ("%s%s", dir
, p
);
172 return str_dup (str
);
175 /* The 'more' parameter lets the calling command process remaining
176 * non-option arguments. */
178 parse_options (char **line
, struct argv_s
* args
[], void *data
, int more
)
191 if (*p
== '-' && *(p
+ 1) == '-')
194 char opt
[255] = { 0 }, value
[255] =
200 if (!*p
|| *p
== ' ')
208 for (tp
= opt
, len
= 0; *p
; p
++, len
++)
211 return GPG_ERR_LINE_TOO_LONG
;
213 if (*p
== ' ' || *p
== '=')
223 for (tp
= value
, len
= 0; *p
; p
++, len
++)
226 return GPG_ERR_LINE_TOO_LONG
;
233 else if (*p
== ' ' && !inquote
)
251 for (int i
= 0; args
[i
]; i
++)
253 if (!strcmp (args
[i
]->opt
, opt
))
255 log_write2 ("param: name='%s' value='%s'", opt
, value
);
256 if (args
[i
]->type
== OPTION_TYPE_NOARG
&& *value
)
257 return GPG_ERR_SYNTAX
;
258 else if (args
[i
]->type
== OPTION_TYPE_ARG
&& !*value
)
259 return GPG_ERR_SYNTAX
;
263 rc
= args
[i
]->func (data
, value
);
274 return GPG_ERR_UNKNOWN_OPTION
;
283 return GPG_ERR_SYNTAX
;
293 bin2hex (const unsigned char *data
, size_t len
)
295 size_t size
= len
* 2 + 1;
301 for (n
= 0; n
< len
; n
++)
305 sprintf (c
, "%02X", data
[n
]);
309 return str_dup (buf
);
313 html_escape (const char *line
, size_t len
, int space
)
315 struct string_s
*string
= string_new ("");
322 for (n
= 0; n
< len
; n
++)
327 string
= string_append (string
, "<");
330 string
= string_append (string
, ">");
335 string
= string_append (string
, "%20");
339 string
= string_append_printf (string
, "%c", line
[n
]);
345 string_free (string
, 0);
350 strip_texi_html (const char *line
)
355 struct string_s
*string
= string_new ("<html><body>");
360 /* The command usage text. */
361 p
= strchr (line
, '\n');
364 len
= strlen (line
)-strlen(p
);
365 tmp
= html_escape (line
, len
, 0);
366 string
= string_append_printf (string
, "<b>%s</b><p>", tmp
);
381 if (*p
== '@' && *(p
+ 1) != '@')
385 if (!strncasecmp (p
, "end ", 4))
388 if (!strncasecmp (p
, "table", 5))
390 string
= string_append (string
, "</p>");
392 else if (!strncasecmp (p
, "example", 7))
394 string
= string_append (string
, "</code>");
397 while (*p
++ != '\n');
401 else if (!strncasecmp (p
, "table ", 6))
403 while (*p
++ != '\n');
407 else if (!strncasecmp (p
, "example", 7))
409 string
= string_append (string
, "<code>");
410 while (*p
++ != '\n');
414 else if (!strncasecmp (p
, "sp ", 3))
416 while (*p
++ != '\n');
418 string
= string_append (string
, "<p>");
421 else if (!strncasecmp (p
, "item ", 5))
424 string
= string_append (string
, "<p><b>");
425 tmp
= strchr (p
, '\n');
426 len
= strlen (p
) - strlen (tmp
);
431 string
= string_append (string
, "<");
436 string
= string_append (string
, ">");
440 string
= string_append_printf (string
, "%c", *p
++);
443 string
= string_append (string
, "</b><br/>");
446 else if (!strncasecmp (p
, "pxref", 5)
447 || !strncasecmp (p
, "npxref", 6))
451 if (!strncasecmp (p
, "npxref", 6))
456 string
= string_append_printf (string
, "%s<a href=\"",
460 else if (!strncasecmp (p
, "xref", 4))
464 string
= string_append (string
, "See <a href=\"");
467 else if (!strncasecmp (p
, "url", 3))
471 string
= string_append (string
, "<a href=\"");
474 else if (!strncasecmp (p
, "key", 3))
479 else if (!strncasecmp (p
, "file", 4))
483 string
= string_append (string
, "<var>");
486 else if (!strncasecmp (p
, "var", 3))
490 string
= string_append (string
, "<var>");
493 else if (!strncasecmp (p
, "option", 6))
497 string
= string_append (string
, "<var>");
500 else if (!strncasecmp (p
, "code", 4))
504 string
= string_append (string
, "<b>");
507 else if (!strncasecmp (p
, "emph", 4))
511 string
= string_append (string
, "<em>");
514 else if (!strncasecmp (p
, "command", 7))
518 string
= string_append (string
, "<em>");
521 else if (!strncasecmp (p
, "cite", 4))
525 string
= string_append (string
, "<cite>");
528 else if (!strncasecmp (p
, "abbr", 4))
532 string
= string_append (string
, "<em>");
535 else if (!strncasecmp (p
, "*", 1))
537 string
= string_append (string
, "<br/>");
541 while (*p
&& *p
!= '{')
555 tmp
= strchr (p
, '}');
556 len
= strlen (p
) - strlen (tmp
);
568 tmp
= html_escape (buf
, strlen (buf
), 1);
569 string
= string_append_printf (string
, "%s\">%s</a>", tmp
, buf
);
573 string
= string_append (string
, buf
);
576 string
= string_append (string
, "</var>");
578 string
= string_append (string
, "</b>");
580 string
= string_append (string
, "</em>");
582 string
= string_append (string
, "</cite>");
585 else if (*p
== '@' && *(p
+ 1) == '@')
589 string
= string_append_printf (string
, "%c", *p
);
595 string
= string_append (string
, "</body></html>");
597 string_free (string
, 0);
602 strip_texi (const char *str
, int html
)
609 return strip_texi_html (str
);
615 for (p
= str
; *p
; p
++)
617 if (*p
== '@' && *(p
+ 1) != '@')
621 if (!strncasecmp (p
, "table", 5)
622 || !strncasecmp (p
, "end ", 4))
624 while (*p
++ != '\n');
628 else if (!strncasecmp (p
, "example", 7)
629 || !strncasecmp (p
, "end ", 4))
631 while (*p
++ != '\n');
635 else if (!strncasecmp (p
, "sp ", 3))
637 while (*p
++ != '\n');
641 else if (!strncasecmp (p
, "item", 4))
644 while (*p
&& *p
!= '\n')
650 else if (!strncasecmp (p
, "pxref", 5))
657 else if (!strncasecmp (p
, "xref", 4))
664 else if (!strncasecmp (p
, "*", 1))
671 while (*p
&& *p
!= '{')
685 while (*p
&& *p
!= '}')
695 else if (*p
== '@' && *(p
+ 1) == '@')
711 strip_texi_and_wrap (const char *str
, int html
)
713 char *tmp
= strip_texi (str
, html
);
714 char *help
= xcalloc (1, strlen (tmp
) * 2 + 1);
718 for (p
= tmp
, ph
= help
, i
= 0; *p
; p
++, i
++)
720 if (i
== 78 || *p
== '\n')
727 while (*(--t
) != ' ')
743 while (*p
!= '\n' && *p
== ' ')
759 free_key (void *data
)
765 create_thread (void *(*cb
) (void *), void *data
,
766 pthread_t
* tid
, int detached
)
771 pthread_attr_init (&attr
);
774 pthread_attr_setdetachstate (&attr
, PTHREAD_CREATE_DETACHED
);
776 n
= pthread_create (tid
, &attr
, cb
, data
);
777 pthread_attr_destroy (&attr
);
778 return gpg_error_from_errno (n
);
782 release_mutex_cb (void *arg
)
784 pthread_mutex_t
*m
= (pthread_mutex_t
*) arg
;
790 close_fd_cb (void *arg
)
792 int fd
= *(int *)arg
;
799 get_checksum_memory (void *data
, size_t size
, unsigned char **r_crc
,
802 size_t len
= gcry_md_get_algo_dlen (GCRY_MD_CRC32
);
803 unsigned char *crc
= xmalloc (len
);
809 return GPG_ERR_ENOMEM
;
811 gcry_md_hash_buffer (GCRY_MD_CRC32
, crc
, data
, size
);
817 /* The advisory lock should be obtained before calling this function. */
819 get_checksum (const char *filename
, unsigned char **r_crc
, size_t * r_crclen
)
826 rc
= open_check_file (filename
, &fd
, &st
, 1);
830 pthread_cleanup_push (close_fd_cb
, &fd
);
831 buf
= xmalloc (st
.st_size
);
834 pthread_cleanup_push (xfree
, buf
);
836 size_t len
= read (fd
, buf
, st
.st_size
);
837 if (len
== st
.st_size
)
840 rc
= get_checksum_memory (buf
, st
.st_size
, r_crc
, r_crclen
);
845 rc
= GPG_ERR_TOO_SHORT
;
847 pthread_cleanup_pop (1);
852 pthread_cleanup_pop (1);
856 wchar_t *str_to_wchar (const char *str
)
863 memset (&ps
, 0, sizeof(mbstate_t));
864 len
= mbsrtowcs (NULL
, &p
, 0, &ps
);
868 wc
= xcalloc (len
+1, sizeof(wchar_t));
873 memset (&ps
, 0, sizeof(mbstate_t));
874 len
= mbsrtowcs (wc
, &p
, len
, &ps
);
885 gnupg_escape (const char *str
)
890 char *buf
= xmalloc (strlen(str
)*4+1), *b
= buf
;
896 for (p
= str
; p
&& *p
; p
++)
922 /* From Beej's Guide to Network Programming. It's a good tutorial. */
924 get_in_addr (struct sockaddr
*sa
)
926 if (sa
->sa_family
== AF_INET
)
927 return &(((struct sockaddr_in
*) sa
)->sin_addr
);
929 return &(((struct sockaddr_in6
*) sa
)->sin6_addr
);
933 open_check_file (const char *filename
, int *r_fd
, struct stat
*r_st
, int reg
)
942 if (lstat (filename
, &st
) == -1)
943 return gpg_err_code (gpg_error_from_syserror ());
945 if (!S_ISREG (st
.st_mode
))
946 return GPG_ERR_ENODEV
;
949 memcpy (r_st
, &st
, sizeof (struct stat
));
954 fd
= open (filename
, O_RDONLY
);
956 return gpg_err_code (gpg_error_from_syserror ());
958 if (r_st
&& fstat (fd
, r_st
) == -1)
960 rc
= gpg_err_code (gpg_error_from_syserror ());