1 /*
2 * File: misc_new.c
3 *
4 * Copyright 2008 Jorge Arellano Cid <jcid@dillo.org>
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
12 #include <errno.h> /* errno, err-codes */
13 #include <unistd.h>
14 #include <time.h>
15 #include <sys/stat.h> /* stat */
16 #include <stdlib.h> /* rand, srand */
17
18 #include "../dlib/dlib.h"
19 #include "dpid_common.h"
20 #include "misc_new.h" /* for function prototypes */
21
22 /*! Reads a dpi tag from a socket
23 * \li Continues after a signal interrupt
24 * \Return
25 * Dstr pointer to tag on success, NULL on failure
26 * \important Caller is responsible for freeing the returned Dstr *
27 */
a_Misc_rdtag(int socket)28 Dstr *a_Misc_rdtag(int socket)
29 {
30 char c = '\0';
31 ssize_t rdlen;
32 Dstr *tag;
33
34 tag = dStr_sized_new(64);
35
36 errno = 0;
37
38 do {
39 rdlen = read(socket, &c, 1);
40 if (rdlen == -1 && errno != EINTR)
41 break;
42 dStr_append_c(tag, c);
43 } while (c != '>');
44
45 if (rdlen == -1) {
46 perror("a_Misc_rdtag");
47 dStr_free(tag, TRUE);
48 return (NULL);
49 }
50 return (tag);
51 }
52
53 /*!
54 * Read a dpi tag from sock
55 * \return
56 * pointer to dynamically allocated request tag
57 */
a_Misc_readtag(int sock)58 char *a_Misc_readtag(int sock)
59 {
60 char *tag, c;
61 size_t i;
62 size_t taglen = 0, tagmem = 10;
63 ssize_t rdln = 1;
64
65 tag = NULL;
66 // new start
67 tag = (char *) dMalloc(tagmem + 1);
68 for (i = 0; (rdln = read(sock, &c, 1)) != 0; i++) {
69 if (i == tagmem) {
70 tagmem += tagmem;
71 tag = (char *) dRealloc(tag, tagmem + 1);
72 }
73 tag[i] = c;
74 taglen += rdln;
75 if (c == '>') {
76 tag[i + 1] = '\0';
77 break;
78 }
79 }
80 // new end
81 if (rdln == -1) {
82 ERRMSG("a_Misc_readtag", "read", errno);
83 }
84
85 return (tag);
86 }
87
88 /*! Reads a dpi tag from a socket without hanging on read.
89 * \li Continues after a signal interrupt
90 * \Return
91 * \li 1 on success
92 * \li 0 if input is not available within timeout microseconds.
93 * \li -1 on failure
94 * \important Caller is responsible for freeing the returned Dstr *
95 */
96 /* Is this useful?
97 int a_Misc_nohang_rdtag(int socket, int timeout, Dstr **tag)
98 {
99 int n_fd;
100 fd_set sock_set, select_set;
101 struct timeval tout;
102
103 FD_ZERO(&sock_set);
104 FD_SET(socket, &sock_set);
105
106 errno = 0;
107 do {
108 select_set = sock_set;
109 tout.tv_sec = 0;
110 tout.tv_usec = timeout;
111 n_fd = select(socket + 1, &select_set, NULL, NULL, &tout);
112 } while (n_fd == -1 && errno == EINTR);
113
114 if (n_fd == -1) {
115 MSG_ERR("%s:%d: a_Misc_nohang_rdtag: %s\n",
116 __FILE__, __LINE__, dStrerror(errno));
117 return(-1);
118 }
119 if (n_fd == 0) {
120 return(0);
121 } else {
122 *tag = a_Misc_rdtag(socket);
123 return(1);
124 }
125 }
126 */
127
128 /*
129 * Alternative to mkdtemp().
130 * Not as strong as mkdtemp, but enough for creating a directory.
131 */
a_Misc_mkdtemp(char * template)132 char *a_Misc_mkdtemp(char *template)
133 {
134 for (;;) {
135 if (a_Misc_mkfname(template) && mkdir(template, 0700) == 0)
136 break;
137 if (errno == EEXIST)
138 continue;
139 return 0;
140 }
141 return template;
142 }
143
144 /*
145 * Return a new, nonexistent file name from a template
146 * (adapted from dietlibc; alternative to mkdtemp())
147 */
a_Misc_mkfname(char * template)148 char *a_Misc_mkfname(char *template)
149 {
150 char *tmp = template + strlen(template) - 6;
151 int i;
152 uint_t random;
153 struct stat stat_buf;
154
155 if (tmp < template)
156 goto error;
157 for (i = 0; i < 6; ++i)
158 if (tmp[i] != 'X') {
159 error:
160 errno = EINVAL;
161 return 0;
162 }
163 srand((uint_t)(time(0) ^ getpid()));
164
165 for (;;) {
166 random = (unsigned) rand();
167 for (i = 0; i < 6; ++i) {
168 int hexdigit = (random >> (i * 5)) & 0x1f;
169
170 tmp[i] = hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0';
171 }
172 if (stat(template, &stat_buf) == -1 && errno == ENOENT)
173 return template;
174
175 MSG_ERR("a_Misc_mkfname: another round for %s \n", template);
176 }
177 }
178
179 /*
180 * Return a new, random hexadecimal string of 'nchar' characters.
181 */
a_Misc_mksecret(int nchar)182 char *a_Misc_mksecret(int nchar)
183 {
184 int i;
185 uint_t random;
186 char *secret = dNew(char, nchar + 1);
187
188 srand((uint_t)(time(0) ^ getpid()));
189 random = (unsigned) rand();
190 for (i = 0; i < nchar; ++i) {
191 int hexdigit = (random >> (i * 5)) & 0x0f;
192
193 secret[i] = hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0';
194 }
195 secret[i] = 0;
196 MSG("a_Misc_mksecret: %s\n", secret);
197
198 return secret;
199 }
200
201