1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00
putty-source/unix/uxmisc.c
Simon Tatham aba05b7180 Patch from Robert de Bath to substantially simplify timing.c.
The previous platform-dependent ifdefs, switching between a system
which tried to cope with spurious callbacks (which I'd observed on
Windows) and one which tried to cope with system clock jumps (which
can happen on Unix, if you use gettimeofday) have been completely
removed, and replaced with a much simpler approach which just copes
with system clock jumps by triggering any timers immediately.

None of the resulting effects should be catastrophic (the worst thing
might be the waste of CPU in a spurious rekey, but as long as the
system clock isn't jumping around _all_ the time that's hardly
critical) and in any case the Unix port has had a long-standing oddity
involving occasional lockups if pterm or PuTTY runs for too long,
which hopefully this should replace with a much less bad failure mode.
And the code is much simpler, which is not to be sneezed at.

[originally from svn r9528]
2012-05-13 15:59:26 +00:00

213 lines
4.5 KiB
C

/*
* PuTTY miscellaneous Unix stuff
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <pwd.h>
#include "putty.h"
unsigned long getticks(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
/*
* We want to use milliseconds rather than microseconds,
* because we need a decent number of them to fit into a 32-bit
* word so it can be used for keepalives.
*/
return tv.tv_sec * TICKSPERSEC + tv.tv_usec / (1000000 / TICKSPERSEC);
}
Filename *filename_from_str(const char *str)
{
Filename *ret = snew(Filename);
ret->path = dupstr(str);
return ret;
}
Filename *filename_copy(const Filename *fn)
{
return filename_from_str(fn->path);
}
const char *filename_to_str(const Filename *fn)
{
return fn->path;
}
int filename_equal(const Filename *f1, const Filename *f2)
{
return !strcmp(f1->path, f2->path);
}
int filename_is_null(const Filename *fn)
{
return !fn->path[0];
}
void filename_free(Filename *fn)
{
sfree(fn->path);
sfree(fn);
}
int filename_serialise(const Filename *f, void *vdata)
{
char *data = (char *)vdata;
int len = strlen(f->path) + 1; /* include trailing NUL */
if (data) {
strcpy(data, f->path);
}
return len;
}
Filename *filename_deserialise(void *vdata, int maxsize, int *used)
{
char *data = (char *)vdata;
char *end;
end = memchr(data, '\0', maxsize);
if (!end)
return NULL;
end++;
*used = end - data;
return filename_from_str(data);
}
#ifdef DEBUG
static FILE *debug_fp = NULL;
void dputs(char *buf)
{
if (!debug_fp) {
debug_fp = fopen("debug.log", "w");
}
write(1, buf, strlen(buf));
fputs(buf, debug_fp);
fflush(debug_fp);
}
#endif
char *get_username(void)
{
struct passwd *p;
uid_t uid = getuid();
char *user, *ret = NULL;
/*
* First, find who we think we are using getlogin. If this
* agrees with our uid, we'll go along with it. This should
* allow sharing of uids between several login names whilst
* coping correctly with people who have su'ed.
*/
user = getlogin();
setpwent();
if (user)
p = getpwnam(user);
else
p = NULL;
if (p && p->pw_uid == uid) {
/*
* The result of getlogin() really does correspond to
* our uid. Fine.
*/
ret = user;
} else {
/*
* If that didn't work, for whatever reason, we'll do
* the simpler version: look up our uid in the password
* file and map it straight to a name.
*/
p = getpwuid(uid);
if (!p)
return NULL;
ret = p->pw_name;
}
endpwent();
return dupstr(ret);
}
/*
* Display the fingerprints of the PGP Master Keys to the user.
* (This is here rather than in uxcons because it's appropriate even for
* Unix GUI apps.)
*/
void pgp_fingerprints(void)
{
fputs("These are the fingerprints of the PuTTY PGP Master Keys. They can\n"
"be used to establish a trust path from this executable to another\n"
"one. See the manual for more information.\n"
"(Note: these fingerprints have nothing to do with SSH!)\n"
"\n"
"PuTTY Master Key (RSA), 1024-bit:\n"
" " PGP_RSA_MASTER_KEY_FP "\n"
"PuTTY Master Key (DSA), 1024-bit:\n"
" " PGP_DSA_MASTER_KEY_FP "\n", stdout);
}
/*
* Set FD_CLOEXEC on a file descriptor
*/
int cloexec(int fd) {
int fdflags;
fdflags = fcntl(fd, F_GETFD);
if (fdflags == -1) return -1;
return fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
}
FILE *f_open(const Filename *filename, char const *mode, int is_private)
{
if (!is_private) {
return fopen(filename->path, mode);
} else {
int fd;
assert(mode[0] == 'w'); /* is_private is meaningless for read,
and tricky for append */
fd = open(filename->path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0)
return NULL;
return fdopen(fd, mode);
}
}
FontSpec *fontspec_new(const char *name)
{
FontSpec *f = snew(FontSpec);
f->name = dupstr(name);
return f;
}
FontSpec *fontspec_copy(const FontSpec *f)
{
return fontspec_new(f->name);
}
void fontspec_free(FontSpec *f)
{
sfree(f->name);
sfree(f);
}
int fontspec_serialise(FontSpec *f, void *data)
{
int len = strlen(f->name);
if (data)
strcpy(data, f->name);
return len + 1; /* include trailing NUL */
}
FontSpec *fontspec_deserialise(void *vdata, int maxsize, int *used)
{
char *data = (char *)vdata;
char *end = memchr(data, '\0', maxsize);
if (!end)
return NULL;
*used = end - data + 1;
return fontspec_new(data);
}