"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "fileio.c" between
screen-4.8.0.tar.gz and screen-4.9.0.tar.gz

About: GNU screen is a screen manager with VT100/ANSI terminal emulation (multiplexing up to 10 pseudo-terminals).

fileio.c  (screen-4.8.0):fileio.c  (screen-4.9.0)
skipping to change at line 45 skipping to change at line 45
# include <signal.h> # include <signal.h>
#endif #endif
#include "config.h" #include "config.h"
#include "screen.h" #include "screen.h"
#include "extern.h" #include "extern.h"
extern struct display *display, *displays; extern struct display *display, *displays;
extern struct win *fore; extern struct win *fore;
extern struct layer *flayer; extern struct layer *flayer;
extern int ServerSocket; extern int ServerSocket;
extern int real_uid, eff_uid; extern int real_uid, eff_uid;
extern int real_gid, eff_gid; extern int real_gid, eff_gid;
extern char *extra_incap, *extra_outcap; extern char *extra_incap, *extra_outcap;
extern char *home, *RcFileName; extern char *home, *RcFileName;
extern char SockPath[], *SockName; extern char SockPath[], *SockName;
#ifdef COPY_PASTE #ifdef COPY_PASTE
extern char *BufferFile; extern char *BufferFile;
#endif #endif
extern int hardcopy_append; extern int hardcopy_append;
extern char *hardcopydir; extern char *hardcopydir;
static char *CatExtra __P((char *, char *)); static char *CatExtra __P((char *, char *));
static char *findrcfile __P((char *)); static char *findrcfile __P((char *));
char *rc_name = ""; char *rc_name = "";
int rc_recursion = 0; int rc_recursion = 0;
static char * CatExtra(register char *str1, register char *str2) { static char *
register char *cp; CatExtra(register char *str1, register char *str2)
register int len1, len2, add_colon; {
register char *cp;
len1 = strlen(str1); register int len1, len2, add_colon;
if (len1 == 0)
return str2; len1 = strlen(str1);
add_colon = (str1[len1 - 1] != ':'); if (len1 == 0)
if (str2) { return str2;
len2 = strlen(str2); add_colon = (str1[len1 - 1] != ':');
if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL) if (str2) {
Panic(0, "%s", strnomem); len2 = strlen(str2);
bcopy(cp, cp + len1 + add_colon, len2 + 1); if ((cp = realloc(str2, (unsigned)len1 + len2 + add_colon + 1)) =
} = NULL)
else { Panic(0, "%s", strnomem);
if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL) bcopy(cp, cp + len1 + add_colon, len2 + 1);
Panic(0, "%s", strnomem); } else {
cp[len1 + add_colon] = '\0'; if ((cp = malloc((unsigned)len1 + add_colon + 1)) == NULL)
} Panic(0, "%s", strnomem);
bcopy(str1, cp, len1); cp[len1 + add_colon] = '\0';
if (add_colon) }
cp[len1] = ':'; bcopy(str1, cp, len1);
return cp; if (add_colon)
} cp[len1] = ':';
return cp;
static char *findrcfile(char *rcfile) { }
char buf[256];
char *p; static char *
findrcfile(char *rcfile)
/* Tilde prefix support courtesy <hesso@pool.math.tu-berlin.de>, {
* taken from a Debian patch. */ char buf[256];
if (rcfile && *rcfile == '~') { char *p;
static char rcfilename_tilde_exp[MAXPATHLEN+1];
char *slash_position = strchr(rcfile, '/'); /* Tilde prefix support courtesy <hesso@pool.math.tu-berlin.de>,
* taken from a Debian patch. */
if (slash_position == rcfile+1) { if (rcfile && *rcfile == '~') {
char *home = getenv("HOME"); static char rcfilename_tilde_exp[MAXPATHLEN + 1];
if (!home) { char *slash_position = strchr(rcfile, '/');
Msg(0, "%s: source: tilde expansion failed", rc_name);
return NULL; if (slash_position == rcfile + 1) {
} char *home = getenv("HOME");
snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", home, rcfile+2); if (!home) {
} Msg(0, "%s: source: tilde expansion failed", rc_n
else if (slash_position) { ame);
struct passwd *p; return NULL;
*slash_position = 0; }
p = getpwnam(rcfile+1); snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", home,
if (!p){ rcfile + 2);
Msg(0, "%s: source: tilde expansion failed for user %s", rc_name, rcfile } else if (slash_position) {
+1); struct passwd *p;
return NULL; *slash_position = 0;
} p = getpwnam(rcfile + 1);
snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", p->pw_dir, slash_posit if (!p) {
ion+1); Msg(0, "%s: source: tilde expansion failed for us
} er %s", rc_name, rcfile + 1);
else { return NULL;
Msg(0, "%s: source: illegal tilde expression.", rc_name); }
return NULL; snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", p->pw
} _dir, slash_position + 1);
rcfile = rcfilename_tilde_exp; } else {
} Msg(0, "%s: source: illegal tilde expression.", rc_name);
return NULL;
if (rcfile) { }
char *rcend = rindex(rc_name, '/'); rcfile = rcfilename_tilde_exp;
if (*rcfile != '/' && rcend && (rcend - rc_name) + strlen(rcfile) + 2 < size }
of(buf)) {
strncpy(buf, rc_name, rcend - rc_name + 1); if (rcfile) {
strcpy(buf + (rcend - rc_name) + 1, rcfile); char *rcend = rindex(rc_name, '/');
if (access(buf, R_OK) == 0) if (*rcfile != '/' && rcend && (rcend - rc_name) + strlen(rcfile)
return SaveStr(buf); + 2 < sizeof(buf)) {
} strncpy(buf, rc_name, rcend - rc_name + 1);
debug1("findrcfile: you specified '%s'\n", rcfile); strcpy(buf + (rcend - rc_name) + 1, rcfile);
return SaveStr(rcfile); if (access(buf, R_OK) == 0)
} return SaveStr(buf);
}
debug("findrcfile: you specified nothing...\n"); debug1("findrcfile: you specified '%s'\n", rcfile);
if ((p = getenv("SCREENRC")) != NULL && *p != '\0') { return SaveStr(rcfile);
debug1(" $SCREENRC has: '%s'\n", p); }
return SaveStr(p);
} debug("findrcfile: you specified nothing...\n");
else { if ((p = getenv("SCREENRC")) != NULL && *p != '\0') {
debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n"); debug1(" $SCREENRC has: '%s'\n", p);
if (strlen(home) > sizeof(buf) - 12) return SaveStr(p);
Panic(0, "Rc: home too large"); } else {
sprintf(buf, "%s/.screenrc", home); debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n");
return SaveStr(buf); if (strlen(home) > sizeof(buf) - 12)
} Panic(0, "Rc: home too large");
sprintf(buf, "%s/.screenrc", home);
return SaveStr(buf);
}
} }
/* /*
* this will be called twice: * this will be called twice:
* 1) rcfilename = "/etc/screenrc" * 1) rcfilename = "/etc/screenrc"
* 2) rcfilename = RcFileName * 2) rcfilename = RcFileName
*/ */
int StartRc(char *rcfilename, int nopanic) { int
register int argc, len; StartRc(char *rcfilename, int nopanic)
register char *p, *cp; {
char buf[2048]; register int argc, len;
char *args[MAXARGS]; register char *p, *cp;
int argl[MAXARGS]; char buf[2048];
FILE *fp; char *args[MAXARGS];
char *oldrc_name = rc_name; int argl[MAXARGS];
FILE *fp;
/* always fix termcap/info capabilities */ char *oldrc_name = rc_name;
extra_incap = CatExtra("TF", extra_incap);
/* always fix termcap/info capabilities */
/* Special settings for vt100 and others */ extra_incap = CatExtra("TF", extra_incap);
if (display && (!strncmp(D_termname, "vt", 2) || !strncmp(D_termname, "xterm",
5))) /* Special settings for vt100 and others */
extra_incap = CatExtra("xn:f0=\033Op:f1=\033Oq:f2=\033Or:f3=\033Os:f4=\033Ot if (display && (!strncmp(D_termname, "vt", 2) || !strncmp(D_termname, "xt
:f5=\033Ou:f6=\033Ov:f7=\033Ow:f8=\033Ox:f9=\033Oy:f.=\033On:f,=\033Ol:fe=\033OM erm", 5)))
:f+=\033Ok:f-=\033Om:f*=\033Oj:f/=\033Oo:fq=\033OX", extra_incap); extra_incap = CatExtra("xn:f0=\033Op:f1=\033Oq:f2=\033Or:f3=\033O
s:f4=\033Ot:f5=\033Ou:f6=\033Ov:f7=\033Ow:f8=\033Ox:f9=\033Oy:f.=\033On:f,=\033O
rc_name = findrcfile(rcfilename); l:fe=\033OM:f+=\033Ok:f-=\033Om:f*=\033Oj:f/=\033Oo:fq=\033OX", extra_incap);
if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) {
const char *rc_nonnull = rc_name ? rc_name : rcfilename; rc_name = findrcfile(rcfilename);
if (!rc_recursion && RcFileName && !strcmp(RcFileName, rc_nonnull)) { if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) {
/* const char *rc_nonnull = rc_name ? rc_name : rcfilename;
* User explicitly gave us that name, if (!rc_recursion && RcFileName && !strcmp(RcFileName, rc_nonnull
* this is the only case, where we get angry, if we can't read )) {
* the file. /*
*/ * User explicitly gave us that name,
debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name ? rc_name : "(nul * this is the only case, where we get angry, if we can't read
l)", rcfilename); * the file.
if (!nopanic) Panic(0, "Unable to open \"%s\".", rc_nonnull); */
/* possibly NOTREACHED */ debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name
} ? rc_name : "(null)", rcfilename);
if (!nopanic)
debug1("StartRc: '%s' no good. ignored\n", rc_nonnull); Panic(0, "Unable to open \"%s\".", rc_nonnull);
if (rc_name) /* possibly NOTREACHED */
Free(rc_name); }
rc_name = oldrc_name;
return 1; debug1("StartRc: '%s' no good. ignored\n", rc_nonnull);
} if (rc_name)
while (fgets(buf, sizeof buf, fp) != NULL) { Free(rc_name);
if ((p = rindex(buf, '\n')) != NULL) rc_name = oldrc_name;
*p = '\0'; return 1;
}
if ((argc = Parse(buf, sizeof buf, args, argl)) == 0) while (fgets(buf, sizeof buf, fp) != NULL) {
continue; if ((p = rindex(buf, '\n')) != NULL)
*p = '\0';
if (strcmp(args[0], "echo") == 0) {
if (!display) if ((argc = Parse(buf, sizeof buf, args, argl)) == 0)
continue; continue;
if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3) {
Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name); if (strcmp(args[0], "echo") == 0) {
continue; if (!display)
} continue;
AddStr(args[argc - 1]); if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || a
if (argc != 3) { rgc > 3) {
AddStr("\r\n"); Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc
Flush(0); _name);
} continue;
} }
AddStr(args[argc - 1]);
else if (strcmp(args[0], "sleep") == 0) { if (argc != 3) {
if (!display) AddStr("\r\n");
continue; Flush(0);
debug("sleeeeeeep\n"); }
if (argc != 2) { } else if (strcmp(args[0], "sleep") == 0) {
Msg(0, "%s: sleep: one numeric argument expected.", rc_name); if (!display)
continue; continue;
} debug("sleeeeeeep\n");
DisplaySleep1000(1000 * atoi(args[1]), 1); if (argc != 2) {
} Msg(0, "%s: sleep: one numeric argument expected.
", rc_name);
continue;
}
DisplaySleep1000(1000 * atoi(args[1]), 1);
}
#ifdef TERMINFO #ifdef TERMINFO
else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "terminfo")) { else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "terminfo")) {
#else #else
else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "termcap")) { else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "ter mcap")) {
#endif #endif
if (!display) if (!display)
continue; continue;
if (argc < 3 || argc > 4) { if (argc < 3 || argc > 4) {
Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]); Msg(0, "%s: %s: incorrect number of arguments.",
continue; rc_name, args[0]);
} continue;
}
for (p = args[1]; p && *p; p = cp) {
if ((cp = index(p, '|')) != 0) for (p = args[1]; p && *p; p = cp) {
*cp++ = '\0'; if ((cp = index(p, '|')) != 0)
len = strlen(p); *cp++ = '\0';
if (p[len - 1] == '*') { len = strlen(p);
if (!(len - 1) || !strncmp(p, D_termname, len - 1)) if (p[len - 1] == '*') {
break; if (!(len - 1) || !strncmp(p, D_termname,
} len - 1))
else if (!strcmp(p, D_termname)) break;
break; } else if (!strcmp(p, D_termname))
} break;
if (!(p && *p)) }
continue; if (!(p && *p))
extra_incap = CatExtra(args[2], extra_incap); continue;
if (argc == 4) extra_incap = CatExtra(args[2], extra_incap);
extra_outcap = CatExtra(args[3], extra_outcap); if (argc == 4)
} extra_outcap = CatExtra(args[3], extra_outcap);
else if (!strcmp(args[0], "source")) { } else if (!strcmp(args[0], "source")) {
if (rc_recursion <= 10) { if (rc_recursion <= 10) {
rc_recursion++; rc_recursion++;
(void)StartRc(args[1], 0); (void)StartRc(args[1], 0);
rc_recursion--; rc_recursion--;
} }
} }
} }
fclose(fp); fclose(fp);
Free(rc_name); Free(rc_name);
rc_name = oldrc_name; rc_name = oldrc_name;
return 0; return 0;
} }
void FinishRc(char *rcfilename) { void
char buf[2048]; FinishRc(char *rcfilename)
FILE *fp; {
char *oldrc_name = rc_name; char buf[2048];
FILE *fp;
rc_name = findrcfile(rcfilename); char *oldrc_name = rc_name;
if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) { rc_name = findrcfile(rcfilename);
const char *rc_nonnull = rc_name ? rc_name : rcfilename;
if (rc_recursion) if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) {
Msg(errno, "%s: source %s", oldrc_name, rc_nonnull); const char *rc_nonnull = rc_name ? rc_name : rcfilename;
else if (RcFileName && !strcmp(RcFileName, rc_nonnull)) { if (rc_recursion)
Msg(errno, "%s: source %s", oldrc_name, rc_nonnull);
else if (RcFileName && !strcmp(RcFileName, rc_nonnull)) {
/* /*
* User explicitly gave us that name, * User explicitly gave us that name,
* this is the only case, where we get angry, if we can't read * this is the only case, where we get angry, if we can't read
* the file. * the file.
*/ */
debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name ? rc_name : "(nul debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name ?
l)", rcfilename); rc_name : "(null)", rcfilename);
Panic(0, "Unable to open \"%s\".", rc_nonnull); Panic(0, "Unable to open \"%s\".", rc_nonnull);
/* NOTREACHED */ /* NOTREACHED */
} }
debug1("FinishRc: '%s' no good. ignored\n", rc_nonnull); debug1("FinishRc: '%s' no good. ignored\n", rc_nonnull);
if (rc_name) if (rc_name)
Free(rc_name); Free(rc_name);
rc_name = oldrc_name; rc_name = oldrc_name;
return; return;
} }
debug("finishrc is going...\n"); debug("finishrc is going...\n");
while (fgets(buf, sizeof buf, fp) != NULL) while (fgets(buf, sizeof buf, fp) != NULL)
RcLine(buf, sizeof buf); RcLine(buf, sizeof buf);
(void) fclose(fp); (void)fclose(fp);
Free(rc_name); Free(rc_name);
rc_name = oldrc_name; rc_name = oldrc_name;
} }
void do_source(char *rcfilename) { void
if (rc_recursion > 10) { do_source(char *rcfilename)
Msg(0, "%s: source: recursion limit reached", rc_name); {
return; if (rc_recursion > 10) {
} Msg(0, "%s: source: recursion limit reached", rc_name);
rc_recursion++; return;
FinishRc(rcfilename); }
rc_recursion--; rc_recursion++;
FinishRc(rcfilename);
rc_recursion--;
} }
/* /*
* Running a Command Line in the environment determined by the display. * Running a Command Line in the environment determined by the display.
* The fore window is taken from the display as well as the user. * The fore window is taken from the display as well as the user.
* This is bad when we run detached. * This is bad when we run detached.
*/ */
void RcLine(char *ubuf, int ubufl) { void
char *args[MAXARGS]; RcLine(char *ubuf, int ubufl)
int argl[MAXARGS]; {
char *args[MAXARGS];
int argl[MAXARGS];
#ifdef MULTIUSER #ifdef MULTIUSER
extern struct acluser *EffectiveAclUser; /* acl.c */ extern struct acluser *EffectiveAclUser; /* acl.c */
extern struct acluser *users; /* acl.c */ extern struct acluser *users; /* acl.c */
#endif #endif
if (display) { if (display) {
fore = D_fore; fore = D_fore;
flayer = D_forecv->c_layer; flayer = D_forecv->c_layer;
} } else
else flayer = fore ? fore->w_savelayer : 0;
flayer = fore ? fore->w_savelayer : 0; if (Parse(ubuf, ubufl, args, argl) <= 0)
if (Parse(ubuf, ubufl, args, argl) <= 0) return;
return;
#ifdef MULTIUSER #ifdef MULTIUSER
if (!display) { if (!display) {
/* the session owner does it, when there is no display here */ /* the session owner does it, when there is no display here */
EffectiveAclUser = users; EffectiveAclUser = users;
debug("RcLine: WARNING, no display no user! Session owner executes command debug("RcLine: WARNING, no display no user! Session owner execute
\n"); s command\n");
} }
#endif #endif
DoCommand(args, argl); DoCommand(args, argl);
#ifdef MULTIUSER #ifdef MULTIUSER
EffectiveAclUser = 0; EffectiveAclUser = 0;
#endif #endif
} }
/* needs display for copybuffer access and termcap dumping */ /* needs display for copybuffer access and termcap dumping */
void WriteFile(struct acluser *user, char *fn, int dump) { void
WriteFile(struct acluser *user, char *fn, int dump)
{
/* dump==0: create .termcap, /* dump==0: create .termcap,
* dump==1: hardcopy, * dump==1: hardcopy,
* #ifdef COPY_PASTE * #ifdef COPY_PASTE
* dump==2: BUFFERFILE * dump==2: BUFFERFILE
* #endif COPY_PASTE * #endif COPY_PASTE
* dump==1: scrollback, * dump==1: scrollback,
*/ */
register int i, j, k; register int i, j, k;
register char *p; register char *p;
register FILE *f; register FILE *f;
char fnbuf[1024]; char fnbuf[1024];
char *mode = "w"; char *mode = "w";
#ifdef COPY_PASTE #ifdef COPY_PASTE
int public = 0; int public = 0;
# ifdef HAVE_LSTAT # ifdef HAVE_LSTAT
struct stat stb, stb2; struct stat stb, stb2;
int fd, exists = 0; int fd, exists = 0;
# endif # endif
#endif #endif
switch (dump) { switch (dump) {
case DUMP_TERMCAP: case DUMP_TERMCAP:
if (fn == 0) { if (fn == 0) {
i = SockName - SockPath; i = SockName - SockPath;
if (i > (int)sizeof(fnbuf) - 9) if (i > (int)sizeof(fnbuf) - 9)
i = 0; i = 0;
strncpy(fnbuf, SockPath, i); strncpy(fnbuf, SockPath, i);
strcpy(fnbuf + i, ".termcap"); strcpy(fnbuf + i, ".termcap");
fn = fnbuf; fn = fnbuf;
} }
break; break;
case DUMP_HARDCOPY: case DUMP_HARDCOPY:
case DUMP_SCROLLBACK: case DUMP_SCROLLBACK:
if (fn == 0) { if (fn == 0) {
if (fore == 0) if (fore == 0)
return; return;
if (hardcopydir && *hardcopydir && strlen(hardcopydir) < sizeof(fnbuf) - if (hardcopydir && *hardcopydir && strlen(hardcopydir) <
21) sizeof(fnbuf) - 21)
sprintf(fnbuf, "%s/hardcopy.%d", hardcopydir, fore->w_number); sprintf(fnbuf, "%s/hardcopy.%d", hardcopydir, for
else e->w_number);
sprintf(fnbuf, "hardcopy.%d", fore->w_number); else
fn = fnbuf; sprintf(fnbuf, "hardcopy.%d", fore->w_number);
} fn = fnbuf;
if (hardcopy_append && !access(fn, W_OK)) }
mode = "a"; if (hardcopy_append && !access(fn, W_OK))
break; mode = "a";
break;
#ifdef COPY_PASTE #ifdef COPY_PASTE
case DUMP_EXCHANGE: case DUMP_EXCHANGE:
if (fn == 0) { if (fn == 0) {
strncpy(fnbuf, BufferFile, sizeof(fnbuf) - 1); strncpy(fnbuf, BufferFile, sizeof(fnbuf) - 1);
fnbuf[sizeof(fnbuf) - 1] = 0; fnbuf[sizeof(fnbuf) - 1] = 0;
fn = fnbuf; fn = fnbuf;
} }
public = !strcmp(fn, DEFAULT_BUFFERFILE); public = !strcmp(fn, DEFAULT_BUFFERFILE);
# ifdef HAVE_LSTAT # ifdef HAVE_LSTAT
exists = !lstat(fn, &stb); exists = !lstat(fn, &stb);
if (public && exists && (S_ISLNK(stb.st_mode) || stb.st_nlink > 1)) { if (public && exists && (S_ISLNK(stb.st_mode) || stb.st_nlink > 1
Msg(0, "No write to links, please."); )) {
return; Msg(0, "No write to links, please.");
} return;
}
# endif # endif
break; break;
#endif #endif
} }
debug2("WriteFile(%d) %s\n", dump, fn); debug2("WriteFile(%d) %s\n", dump, fn);
if (UserContext() > 0) { if (UserContext() > 0) {
debug("Writefile: usercontext\n"); debug("Writefile: usercontext\n");
#ifdef COPY_PASTE #ifdef COPY_PASTE
if (dump == DUMP_EXCHANGE && public) { if (dump == DUMP_EXCHANGE && public) {
# ifdef HAVE_LSTAT # ifdef HAVE_LSTAT
if (exists) { if (exists) {
if ((fd = open(fn, O_WRONLY, 0666)) >= 0) { if ((fd = open(fn, O_WRONLY, 0666)) >= 0) {
if (fstat(fd, &stb2) == 0 && stb.st_dev == stb2.st_dev && stb.st_ino = if (fstat(fd, &stb2) == 0 && stb.st_dev =
= stb2.st_ino) = stb2.st_dev && stb.st_ino == stb2.st_ino)
ftruncate(fd, 0); ftruncate(fd, 0);
else { else {
close(fd); close(fd);
fd = -1; fd = -1;
} }
} }
} } else
else fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0666);
fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0666); f = fd >= 0 ? fdopen(fd, mode) : 0;
f = fd >= 0 ? fdopen(fd, mode) : 0;
# else # else
f = fopen(fn, mode); f = fopen(fn, mode);
# endif # endif
} } else
else
#endif /* COPY_PASTE */ #endif /* COPY_PASTE */
f = fopen(fn, mode); f = fopen(fn, mode);
if (f == NULL) { if (f == NULL) {
debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode); debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode);
UserReturn(0); UserReturn(0);
} } else {
else { switch (dump) {
switch (dump) { case DUMP_HARDCOPY:
case DUMP_HARDCOPY: case DUMP_SCROLLBACK:
case DUMP_SCROLLBACK: if (!fore)
if (!fore) break;
break; if (*mode == 'a') {
if (*mode == 'a') { putc('>', f);
putc('>', f); for (j = fore->w_width - 2; j > 0; j--)
for (j = fore->w_width - 2; j > 0; j--) putc('=', f);
putc('=', f); fputs("<\n", f);
fputs("<\n", f); }
} if (dump == DUMP_SCROLLBACK) {
if (dump == DUMP_SCROLLBACK) {
#ifdef COPY_PASTE #ifdef COPY_PASTE
for (i = fore->w_histheight - fore->w_scrollback_height; i < for for (i = fore->w_histheight - fore->w_scr
e->w_histheight; i++) { ollback_height; i < fore->w_histheight; i++) {
p = (char *)(WIN(i)->image); p = (char *)(WIN(i)->image);
for (k = fore->w_width - 1; k >= 0 && p[k] == ' '; k--) for (k = fore->w_width - 1;
; k >= 0 && p[k] == ' '; k--)
for (j = 0; j <= k; j++) ;
putc(p[j], f); for (j = 0; j <= k; j++)
putc('\n', f); putc(p[j], f);
} putc('\n', f);
#endif }
} #endif
for (i = 0; i < fore->w_height; i++) { }
p = (char *)fore->w_mlines[i].image; for (i = 0; i < fore->w_height; i++) {
for (k = fore->w_width - 1; k >= 0 && p[k] == ' '; k--) p = (char *)fore->w_mlines[i].image;
; for (k = fore->w_width - 1;
for (j = 0; j <= k; j++) k >= 0 && p[k] == ' '; k--)
putc(p[j], f); ;
putc('\n', f); for (j = 0; j <= k; j++)
} putc(p[j], f);
break; putc('\n', f);
}
case DUMP_TERMCAP: break;
DumpTermcap(fore->w_aflag, f);
break; case DUMP_TERMCAP:
DumpTermcap(fore->w_aflag, f);
break;
#ifdef COPY_PASTE #ifdef COPY_PASTE
case DUMP_EXCHANGE: case DUMP_EXCHANGE:
p = user->u_plop.buf; p = user->u_plop.buf;
for (i = user->u_plop.len; i-- > 0; p++) for (i = user->u_plop.len; i-- > 0; p++)
if (*p == '\r' && (i == 0 || p[1] != '\n')) if (*p == '\r' && (i == 0 || p[1] != '\n'
putc('\n', f); ))
else putc('\n', f);
putc(*p, f); else
break; putc(*p, f);
#endif break;
} #endif
(void) fclose(f); }
UserReturn(1); (void)fclose(f);
} UserReturn(1);
} }
if (UserStatus() <= 0) }
Msg(0, "Cannot open \"%s\"", fn); if (UserStatus() <= 0)
else if (display && !*rc_name) { Msg(0, "Cannot open \"%s\"", fn);
switch (dump) { else if (display && !*rc_name) {
case DUMP_TERMCAP: switch (dump) {
Msg(0, "Termcap entry written to \"%s\".", fn); case DUMP_TERMCAP:
break; Msg(0, "Termcap entry written to \"%s\".", fn);
case DUMP_HARDCOPY: break;
case DUMP_SCROLLBACK: case DUMP_HARDCOPY:
Msg(0, "Screen image %s to \"%s\".", (*mode == 'a') ? "appended" : "writ case DUMP_SCROLLBACK:
ten", fn); Msg(0, "Screen image %s to \"%s\".", (*mode == 'a') ? "ap
break; pended" : "written", fn);
break;
#ifdef COPY_PASTE #ifdef COPY_PASTE
case DUMP_EXCHANGE: case DUMP_EXCHANGE:
Msg(0, "Copybuffer written to \"%s\".", fn); Msg(0, "Copybuffer written to \"%s\".", fn);
#endif #endif
} }
} }
} }
#ifdef COPY_PASTE #ifdef COPY_PASTE
/* /*
* returns an allocated buffer which holds a copy of the file named fn. * returns an allocated buffer which holds a copy of the file named fn.
* lenp (if nonzero) points to a location, where the buffer size should be * lenp (if nonzero) points to a location, where the buffer size should be
* stored. * stored.
*/ */
char *ReadFile(char *fn, int *lenp) { char *
int i, l, size; ReadFile(char *fn, int *lenp)
char c, *bp, *buf; {
struct stat stb; int i, l, size;
char c, *bp, *buf;
ASSERT(lenp); struct stat stb;
debug1("ReadFile(%s)\n", fn);
ASSERT(lenp);
if ((i = secopen(fn, O_RDONLY, 0)) < 0) { debug1("ReadFile(%s)\n", fn);
Msg(errno, "no %s -- no slurp", fn);
return NULL; if ((i = secopen(fn, O_RDONLY, 0)) < 0) {
} Msg(errno, "no %s -- no slurp", fn);
return NULL;
if (fstat(i, &stb)) { }
Msg(errno, "no good %s -- no slurp", fn);
close(i); if (fstat(i, &stb)) {
return NULL; Msg(errno, "no good %s -- no slurp", fn);
} close(i);
size = stb.st_size; return NULL;
}
if ((buf = malloc(size)) == NULL) { size = stb.st_size;
close(i);
Msg(0, "%s", strnomem); if ((buf = malloc(size)) == NULL) {
return NULL; close(i);
} Msg(0, "%s", strnomem);
errno = 0; return NULL;
}
if ((l = read(i, buf, size)) != size) { errno = 0;
if (l < 0)
l = 0; if ((l = read(i, buf, size)) != size) {
Msg(errno, "Got only %d bytes from %s", l, fn); if (l < 0)
} l = 0;
else { Msg(errno, "Got only %d bytes from %s", l, fn);
if (read(i, &c, 1) > 0) } else {
Msg(0, "Slurped only %d characters (of %d) into buffer - try again", l, si if (read(i, &c, 1) > 0)
ze); Msg(0, "Slurped only %d characters (of %d) into buffer -
else try again", l, size);
Msg(0, "Slurped %d characters into buffer", l); else
} Msg(0, "Slurped %d characters into buffer", l);
close(i); }
*lenp = l; close(i);
for (bp = buf; l-- > 0; bp++) *lenp = l;
if (*bp == '\n' && (bp == buf || bp[-1] != '\r')) for (bp = buf; l-- > 0; bp++)
*bp = '\r'; if (*bp == '\n' && (bp == buf || bp[-1] != '\r'))
return buf; *bp = '\r';
} return buf;
}
void KillBuffers() {
if (UserContext() > 0) void
UserReturn(unlink(BufferFile) ? errno : 0); KillBuffers()
errno = UserStatus(); {
Msg(errno, "%s %sremoved", BufferFile, errno ? "not " : ""); if (UserContext() > 0)
UserReturn(unlink(BufferFile) ? errno : 0);
errno = UserStatus();
Msg(errno, "%s %sremoved", BufferFile, errno ? "not " : "");
} }
#endif /* COPY_PASTE */ #endif /* COPY_PASTE */
/* (Almost) secure open and fopen... */ /* (Almost) secure open and fopen... */
FILE *secfopen(char *name, char *mode) { FILE *
FILE *fi; secfopen(char *name, char *mode)
{
FILE *fi;
#ifndef USE_SETEUID #ifndef USE_SETEUID
int flags, fd; int flags, fd;
#endif #endif
debug2("secfopen(%s, %s)\n", name, mode); debug2("secfopen(%s, %s)\n", name, mode);
#ifdef USE_SETEUID #ifdef USE_SETEUID
xseteuid(real_uid); xseteuid(real_uid);
xsetegid(real_gid); xsetegid(real_gid);
fi = fopen(name, mode); fi = fopen(name, mode);
xseteuid(eff_uid); xseteuid(eff_uid);
xsetegid(eff_gid); xsetegid(eff_gid);
return fi; return fi;
#else #else
if (eff_uid == real_uid) if (eff_uid == real_uid)
return fopen(name, mode); return fopen(name, mode);
if (mode[0] && mode[1] == '+') if (mode[0] && mode[1] == '+')
flags = O_RDWR; flags = O_RDWR;
else else
flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY; flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY;
if (mode[0] == 'w') if (mode[0] == 'w')
flags |= O_CREAT | O_TRUNC; flags |= O_CREAT | O_TRUNC;
else if (mode[0] == 'a') else if (mode[0] == 'a')
flags |= O_CREAT | O_APPEND; flags |= O_CREAT | O_APPEND;
else if (mode[0] != 'r') { else if (mode[0] != 'r') {
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
if ((fd = secopen(name, flags, 0666)) < 0) if ((fd = secopen(name, flags, 0666)) < 0)
return 0; return 0;
if ((fi = fdopen(fd, mode)) == 0) { if ((fi = fdopen(fd, mode)) == 0) {
close(fd); close(fd);
return 0; return 0;
} }
return fi; return fi;
#endif #endif
} }
int secopen(char *name, int flags, int mode) { int
int fd; secopen(char *name, int flags, int mode)
{
int fd;
#ifndef USE_SETEUID #ifndef USE_SETEUID
int q; int q;
struct stat stb; struct stat stb;
#endif #endif
debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode); debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode);
#ifdef USE_SETEUID #ifdef USE_SETEUID
xseteuid(real_uid); xseteuid(real_uid);
xsetegid(real_gid); xsetegid(real_gid);
fd = open(name, flags, mode); fd = open(name, flags, mode);
xseteuid(eff_uid); xseteuid(eff_uid);
xsetegid(eff_gid); xsetegid(eff_gid);
return fd; return fd;
#else #else
if (eff_uid == real_uid) if (eff_uid == real_uid)
return open(name, flags, mode); return open(name, flags, mode);
/* Truncation/creation is done in UserContext */
if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK))) { /* Truncation/creation is done in UserContext */
if (UserContext() > 0) { if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK))) {
if ((fd = open(name, flags, mode)) >= 0) { if (UserContext() > 0) {
close(fd); if ((fd = open(name, flags, mode)) >= 0) {
UserReturn(0); close(fd);
} UserReturn(0);
if (errno == 0) }
errno = EACCES; if (errno == 0)
UserReturn(errno); errno = EACCES;
} UserReturn(errno);
if ((q = UserStatus())) { }
if (q > 0) if ((q = UserStatus())) {
errno = q; if (q > 0)
return -1; errno = q;
} return -1;
} }
if (access(name, F_OK)) }
return -1; if (access(name, F_OK))
if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0) return -1;
return -1; if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0)
debug("open successful\n"); return -1;
if (fstat(fd, &stb)) { debug("open successful\n");
close(fd); if (fstat(fd, &stb)) {
return -1; close(fd);
} return -1;
debug("fstat successful\n"); }
if (stb.st_uid != real_uid) { debug("fstat successful\n");
switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { if (stb.st_uid != real_uid) {
case O_RDONLY: switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) {
q = 0004; case O_RDONLY:
break; q = 0004;
case O_WRONLY: break;
q = 0002; case O_WRONLY:
break; q = 0002;
default: break;
q = 0006; default:
break; q = 0006;
} break;
if ((stb.st_mode & q) != q) { }
debug1("secopen: permission denied (%03o)\n", stb.st_mode & 07777); if ((stb.st_mode & q) != q) {
close(fd); debug1("secopen: permission denied (%03o)\n", stb.st_mode
errno = EACCES; & 07777);
return -1; close(fd);
} errno = EACCES;
} return -1;
debug1("secopen ok - returning %d\n", fd); }
return fd; }
#endif debug1("secopen ok - returning %d\n", fd);
} return fd;
#endif
int printpipe(struct win *p, char *cmd) { }
int pi[2];
if (pipe(pi)) { int
WMsg(p, errno, "printing pipe"); printpipe(struct win *p, char *cmd)
return -1; {
} int pi[2];
switch (fork()) { if (pipe(pi)) {
case -1: WMsg(p, errno, "printing pipe");
WMsg(p, errno, "printing fork"); return -1;
return -1; }
case 0: switch (fork()) {
display = p->w_pdisplay; case -1:
displays = 0; WMsg(p, errno, "printing fork");
ServerSocket = -1; return -1;
case 0:
display = p->w_pdisplay;
displays = 0;
ServerSocket = -1;
#ifdef DEBUG #ifdef DEBUG
if (dfp && dfp != stderr) if (dfp && dfp != stderr)
fclose(dfp); fclose(dfp);
#endif #endif
close(0); close(0);
dup(pi[0]); dup(pi[0]);
closeallfiles(0); closeallfiles(0);
if (setgid(real_gid) || setuid(real_uid)) if (setgid(real_gid) || setuid(real_uid))
Panic(errno, "printpipe setuid"); Panic(errno, "printpipe setuid");
eff_uid = real_uid; eff_uid = real_uid;
eff_gid = real_gid; eff_gid = real_gid;
#ifdef SIGPIPE #ifdef SIGPIPE
signal(SIGPIPE, SIG_DFL); signal(SIGPIPE, SIG_DFL);
#endif #endif
execl("/bin/sh", "sh", "-c", cmd, (char *)0); execl("/bin/sh", "sh", "-c", cmd, (char *)0);
Panic(errno, "/bin/sh"); Panic(errno, "/bin/sh");
default: default:
break; break;
} }
close(pi[0]); close(pi[0]);
return pi[1]; return pi[1];
} }
int readpipe(char **cmdv) { int
int pi[2]; readpipe(char **cmdv)
{
if (pipe(pi)) { int pi[2];
Msg(errno, "pipe");
return -1; if (pipe(pi)) {
} Msg(errno, "pipe");
return -1;
switch (fork()) { }
case -1:
Msg(errno, "fork"); switch (fork()) {
return -1; case -1:
case 0: Msg(errno, "fork");
displays = 0; return -1;
ServerSocket = -1; case 0:
displays = 0;
ServerSocket = -1;
#ifdef DEBUG #ifdef DEBUG
if (dfp && dfp != stderr) if (dfp && dfp != stderr)
fclose(dfp); fclose(dfp);
#endif #endif
close(1); close(1);
if (dup(pi[1]) != 1) { if (dup(pi[1]) != 1) {
close(pi[1]); close(pi[1]);
Panic(0, "dup"); Panic(0, "dup");
} }
closeallfiles(1); closeallfiles(1);
if (setgid(real_gid) || setuid(real_uid)) { if (setgid(real_gid) || setuid(real_uid)) {
close(1); close(1);
Panic(errno, "setuid/setgid"); Panic(errno, "setuid/setgid");
} }
eff_uid = real_uid; eff_uid = real_uid;
eff_gid = real_gid; eff_gid = real_gid;
#ifdef SIGPIPE #ifdef SIGPIPE
signal(SIGPIPE, SIG_DFL); signal(SIGPIPE, SIG_DFL);
#endif #endif
execvp(*cmdv, cmdv); execvp(*cmdv, cmdv);
close(1); close(1);
Panic(errno, "%s", *cmdv); Panic(errno, "%s", *cmdv);
default: default:
break; break;
} }
close(pi[1]); close(pi[1]);
return pi[0]; return pi[0];
} }
 End of changes. 54 change blocks. 
631 lines changed or deleted 660 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)