Fix a couple of code paths on which, if fxp_readdir returned an error,
[sgt/putty] / unix / uxmisc.c
CommitLineData
f7f27309 1/*
2 * PuTTY miscellaneous Unix stuff
3 */
4
db9b7dce 5#include <fcntl.h>
f7f27309 6#include <stdio.h>
2ac3322e 7#include <stdlib.h>
c6940f12 8#include <assert.h>
d0912d1f 9#include <unistd.h>
92fb929a 10#include <time.h>
f7f27309 11#include <sys/time.h>
799dfcfa 12#include <sys/types.h>
13#include <pwd.h>
f7f27309 14
9a30e26b 15#include "putty.h"
16
f7f27309 17unsigned long getticks(void)
18{
fe7b25bd 19 /*
92fb929a 20 * We want to use milliseconds rather than the microseconds or
21 * nanoseconds given by the underlying clock functions, because we
22 * need a decent number of them to fit into a 32-bit word so it
23 * can be used for keepalives.
fe7b25bd 24 */
92fb929a 25#if defined HAVE_CLOCK_GETTIME && defined HAVE_DECL_CLOCK_MONOTONIC
26 {
27 /* Use CLOCK_MONOTONIC if available, so as to be unconfused if
28 * the system clock changes. */
29 struct timespec ts;
30 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
31 return ts.tv_sec * TICKSPERSEC +
39439af6 32 ts.tv_nsec / (1000000000 / TICKSPERSEC);
92fb929a 33 }
34#endif
35 {
36 struct timeval tv;
37 gettimeofday(&tv, NULL);
38 return tv.tv_sec * TICKSPERSEC + tv.tv_usec / (1000000 / TICKSPERSEC);
39 }
f7f27309 40}
9a30e26b 41
962468d4 42Filename *filename_from_str(const char *str)
9a30e26b 43{
962468d4 44 Filename *ret = snew(Filename);
45 ret->path = dupstr(str);
9a30e26b 46 return ret;
47}
48
962468d4 49Filename *filename_copy(const Filename *fn)
50{
51 return filename_from_str(fn->path);
52}
53
9fab77dc 54const char *filename_to_str(const Filename *fn)
9a30e26b 55{
9fab77dc 56 return fn->path;
9a30e26b 57}
58
962468d4 59int filename_equal(const Filename *f1, const Filename *f2)
60{
61 return !strcmp(f1->path, f2->path);
62}
63
64int filename_is_null(const Filename *fn)
65{
66 return !fn->path[0];
67}
68
69void filename_free(Filename *fn)
9a30e26b 70{
962468d4 71 sfree(fn->path);
72 sfree(fn);
9a30e26b 73}
74
962468d4 75int filename_serialise(const Filename *f, void *vdata)
76{
77 char *data = (char *)vdata;
78 int len = strlen(f->path) + 1; /* include trailing NUL */
79 if (data) {
80 strcpy(data, f->path);
81 }
82 return len;
83}
84Filename *filename_deserialise(void *vdata, int maxsize, int *used)
9a30e26b 85{
962468d4 86 char *data = (char *)vdata;
87 char *end;
88 end = memchr(data, '\0', maxsize);
89 if (!end)
90 return NULL;
91 end++;
92 *used = end - data;
93 return filename_from_str(data);
9a30e26b 94}
d0912d1f 95
96#ifdef DEBUG
97static FILE *debug_fp = NULL;
98
99void dputs(char *buf)
100{
101 if (!debug_fp) {
102 debug_fp = fopen("debug.log", "w");
103 }
104
105 write(1, buf, strlen(buf));
106
107 fputs(buf, debug_fp);
108 fflush(debug_fp);
109}
110#endif
799dfcfa 111
112char *get_username(void)
113{
114 struct passwd *p;
115 uid_t uid = getuid();
116 char *user, *ret = NULL;
117
118 /*
119 * First, find who we think we are using getlogin. If this
120 * agrees with our uid, we'll go along with it. This should
121 * allow sharing of uids between several login names whilst
122 * coping correctly with people who have su'ed.
123 */
124 user = getlogin();
125 setpwent();
126 if (user)
127 p = getpwnam(user);
128 else
129 p = NULL;
130 if (p && p->pw_uid == uid) {
131 /*
132 * The result of getlogin() really does correspond to
133 * our uid. Fine.
134 */
135 ret = user;
136 } else {
137 /*
138 * If that didn't work, for whatever reason, we'll do
139 * the simpler version: look up our uid in the password
140 * file and map it straight to a name.
141 */
142 p = getpwuid(uid);
143 if (!p)
144 return NULL;
145 ret = p->pw_name;
146 }
147 endpwent();
148
149 return dupstr(ret);
150}
2285d016 151
152/*
153 * Display the fingerprints of the PGP Master Keys to the user.
154 * (This is here rather than in uxcons because it's appropriate even for
155 * Unix GUI apps.)
156 */
157void pgp_fingerprints(void)
158{
159 fputs("These are the fingerprints of the PuTTY PGP Master Keys. They can\n"
160 "be used to establish a trust path from this executable to another\n"
161 "one. See the manual for more information.\n"
162 "(Note: these fingerprints have nothing to do with SSH!)\n"
163 "\n"
164 "PuTTY Master Key (RSA), 1024-bit:\n"
165 " " PGP_RSA_MASTER_KEY_FP "\n"
166 "PuTTY Master Key (DSA), 1024-bit:\n"
167 " " PGP_DSA_MASTER_KEY_FP "\n", stdout);
168}
db9b7dce 169
170/*
171 * Set FD_CLOEXEC on a file descriptor
172 */
173int cloexec(int fd) {
174 int fdflags;
175
176 fdflags = fcntl(fd, F_GETFD);
177 if (fdflags == -1) return -1;
178 return fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
179}
c6940f12 180
962468d4 181FILE *f_open(const Filename *filename, char const *mode, int is_private)
c6940f12 182{
183 if (!is_private) {
962468d4 184 return fopen(filename->path, mode);
c6940f12 185 } else {
deb0e1cf 186 int fd;
b078de41 187 assert(mode[0] == 'w'); /* is_private is meaningless for read,
188 and tricky for append */
e41356ff 189 fd = open(filename->path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
c6940f12 190 if (fd < 0)
191 return NULL;
192 return fdopen(fd, mode);
193 }
194}
ae62eaeb 195
196FontSpec *fontspec_new(const char *name)
197{
198 FontSpec *f = snew(FontSpec);
199 f->name = dupstr(name);
200 return f;
201}
202FontSpec *fontspec_copy(const FontSpec *f)
203{
204 return fontspec_new(f->name);
205}
206void fontspec_free(FontSpec *f)
207{
208 sfree(f->name);
209 sfree(f);
210}
211int fontspec_serialise(FontSpec *f, void *data)
212{
213 int len = strlen(f->name);
214 if (data)
215 strcpy(data, f->name);
216 return len + 1; /* include trailing NUL */
217}
218FontSpec *fontspec_deserialise(void *vdata, int maxsize, int *used)
219{
220 char *data = (char *)vdata;
221 char *end = memchr(data, '\0', maxsize);
222 if (!end)
223 return NULL;
224 *used = end - data + 1;
225 return fontspec_new(data);
226}