]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/uxmisc.c
Fix bug in the new CLOCK_MONOTONIC implementation. I was treating the
[PuTTY.git] / unix / uxmisc.c
1 /*
2  * PuTTY miscellaneous Unix stuff
3  */
4
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <unistd.h>
10 #include <time.h>
11 #include <sys/time.h>
12 #include <sys/types.h>
13 #include <pwd.h>
14
15 #include "putty.h"
16
17 unsigned long getticks(void)
18 {
19     /*
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.
24      */
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 +
32                 ts.tv_nsec / (1000000000 / TICKSPERSEC);
33     }
34 #endif
35     {
36         struct timeval tv;
37         gettimeofday(&tv, NULL);
38         return tv.tv_sec * TICKSPERSEC + tv.tv_usec / (1000000 / TICKSPERSEC);
39     }
40 }
41
42 Filename *filename_from_str(const char *str)
43 {
44     Filename *ret = snew(Filename);
45     ret->path = dupstr(str);
46     return ret;
47 }
48
49 Filename *filename_copy(const Filename *fn)
50 {
51     return filename_from_str(fn->path);
52 }
53
54 const char *filename_to_str(const Filename *fn)
55 {
56     return fn->path;
57 }
58
59 int filename_equal(const Filename *f1, const Filename *f2)
60 {
61     return !strcmp(f1->path, f2->path);
62 }
63
64 int filename_is_null(const Filename *fn)
65 {
66     return !fn->path[0];
67 }
68
69 void filename_free(Filename *fn)
70 {
71     sfree(fn->path);
72     sfree(fn);
73 }
74
75 int 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 }
84 Filename *filename_deserialise(void *vdata, int maxsize, int *used)
85 {
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);
94 }
95
96 #ifdef DEBUG
97 static FILE *debug_fp = NULL;
98
99 void 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
111
112 char *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 }
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  */
157 void 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 }
169
170 /*
171  * Set FD_CLOEXEC on a file descriptor
172  */
173 int 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 }
180
181 FILE *f_open(const Filename *filename, char const *mode, int is_private)
182 {
183     if (!is_private) {
184         return fopen(filename->path, mode);
185     } else {
186         int fd;
187         assert(mode[0] == 'w');        /* is_private is meaningless for read,
188                                           and tricky for append */
189         fd = open(filename->path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
190         if (fd < 0)
191             return NULL;
192         return fdopen(fd, mode);
193     }
194 }
195
196 FontSpec *fontspec_new(const char *name)
197 {
198     FontSpec *f = snew(FontSpec);
199     f->name = dupstr(name);
200     return f;
201 }
202 FontSpec *fontspec_copy(const FontSpec *f)
203 {
204     return fontspec_new(f->name);
205 }
206 void fontspec_free(FontSpec *f)
207 {
208     sfree(f->name);
209     sfree(f);
210 }
211 int 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 }
218 FontSpec *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 }