diff --git a/zsnes/src/gui/guimouse.inc b/zsnes/src/gui/guimouse.inc index fa917d55..babeca62 100644 --- a/zsnes/src/gui/guimouse.inc +++ b/zsnes/src/gui/guimouse.inc @@ -711,11 +711,9 @@ ProcessMouseButtons: jne .nostatecancel mov byte[NetStateQuit],1 .nostatecancel -%ifndef __LINUX__ cmp byte[GUICBHold],65 jne .nohomepage call GotoHomepage -%endif .nohomepage mov byte[GUICBHold],0 ret diff --git a/zsnes/src/gui/guiwindp.inc b/zsnes/src/gui/guiwindp.inc index f86e7399..55f72c63 100644 --- a/zsnes/src/gui/guiwindp.inc +++ b/zsnes/src/gui/guiwindp.inc @@ -5214,9 +5214,7 @@ DisplayGUIAbout: je .zero3 mov byte[GUItextcolor],211 .zero3 -%ifndef __LINUX__ DrawGUIButton 11,90,30,175,40,GUIGUIAboutText8,65,0,0 -%endif sub byte[GUItextcolor],15 GUIOuttextwin2 11,6,16,GUIGUIAboutText1 GUIOuttextwin2 11,6,26,GUIGUIAboutText7 diff --git a/zsnes/src/linux/sdlintrf.asm b/zsnes/src/linux/sdlintrf.asm index db7b7af3..035ddca5 100644 --- a/zsnes/src/linux/sdlintrf.asm +++ b/zsnes/src/linux/sdlintrf.asm @@ -124,7 +124,7 @@ EXTSYM WinErrorA2,WinErrorB2,WinErrorC2 EXTSYM GetLocalTime EXTSYM V8Mode,GrayscaleMode EXTSYM PrevWinMode,PrevFSMode -EXTSYM sem_sleep +EXTSYM sem_sleep,ZsnesPage ; NOTE: For timing, Game60hzcall should be called at 50hz or 60hz (depending ; on romispal) after a call to InitPreGame and before DeInitPostGame are @@ -1730,8 +1730,10 @@ NEWSYM WinErrorC call WinErrorC2 ret -; Not supported in Linux NEWSYM GotoHomepage + pushad + call ZsnesPage + popad ret EXTSYM SystemTimewHour diff --git a/zsnes/src/linux/sdllink.c b/zsnes/src/linux/sdllink.c index 016fd991..97a29da0 100644 --- a/zsnes/src/linux/sdllink.c +++ b/zsnes/src/linux/sdllink.c @@ -1179,3 +1179,146 @@ float sem_GetTicks() ticks=((float)(now.tv_sec-sem_start.tv_sec))*1000.f+((float)(now.tv_usec-sem_start.tv_usec))*.001f; return(ticks); } + + + +//Introducing the secure browser opener for POSIX systems ;) -Nach + +#include +#include +#include + +#ifndef OPEN_MAX +#define OPEN_MAX 256 +#endif + +//C++ style code in C +#define bool unsigned char +#define true 1 +#define false 0 + +//Taken from the secure programming cookbook, slightly modified +bool spc_drop_privileges() { + gid_t newgid = getgid(), oldgid = getegid(); + uid_t newuid = getuid(), olduid = geteuid(); + + /* If root privileges are to be dropped, be sure to pare down the ancillary + * groups for the process before doing anything else because the setgroups() + * system call requires root privileges. Drop ancillary groups regardless of + * whether privileges are being dropped temporarily or permanently. + */ + if (!olduid) setgroups(1, &newgid); + + if (newgid != oldgid) { +#if !defined(linux) + setegid(newgid); + if (setgid(newgid) == -1) return(false); +#else + if (setregid(newgid, newgid) == -1) return(false); +#endif + } + + if (newuid != olduid) { +#if !defined(linux) + seteuid(newuid); + if (setuid(newuid) == -1) return(false); +#else + if (setregid(newuid, newuid) == -1) return(false); +#endif + } + + /* verify that the changes were successful */ + + if (newgid != oldgid && (setegid(oldgid) != -1 || getegid() != newgid)) + return(false); + if (newuid != olduid && (seteuid(olduid) != -1 || geteuid() != newuid)) + return(false); + + return(true); +} + +static int open_devnull(int fd) { + FILE *f = 0; + + if (!fd) f = freopen(_PATH_DEVNULL, "rb", stdin); + else if (fd == 1) f = freopen(_PATH_DEVNULL, "wb", stdout); + else if (fd == 2) f = freopen(_PATH_DEVNULL, "wb", stderr); + return (f && fileno(f) == fd); +} + +void spc_sanitize_files() { + int fd, fds; + struct stat st; + + /* Make sure all open descriptors other than the standard ones are closed */ + if ((fds = getdtablesize()) == -1) fds = OPEN_MAX; + for (fd = 3; fd < fds; fd++) close(fd); + + /* Verify that the standard descriptors are open. If they're not, attempt to + * open them using /dev/null. If any are unsuccessful, abort. + */ + for (fd = 0; fd < 3; fd++) + if (fstat(fd, &st) == -1 && (errno != EBADF || !open_devnull(fd))) abort(); +} + +pid_t spc_fork() { + pid_t childpid; + + if ((childpid = fork()) == -1) return -1; + + //If this us the parent proccess nothing more to do + if (childpid != 0) return childpid; + + //This is the child proccess + + spc_sanitize_files(); + + /* + There actually is a bug here which I submitted to the authors of the book -Nach + + The bug is as follows: + The parent returns the child proccess ID in event of success. + The child returns 0 on success if and only if it's spc_drop_privileges() call is successful. + It is possible that the parent will return with a pid > 0, while the child never returns + from spc_fork thus causing a programming error. + + The function should be rewritten that the parent doesn't return till it knows if the + child is able to return or not. And then return -1 or the child pid. + + For out purposes in ZSNES to launch a browser, this bug does not effect us. But + be careful if you copy this code to use somewhere else. + */ + if (!spc_drop_privileges()) //Failed to drop special privliges + { + exit(0); + } + + return 0; +} + +void LaunchBrowser(char *browser) +{ + char *arglist[] = { browser, "http://www.zsnes.com/", 0 }; + execvp(browser, arglist); +} + +void ZsnesPage() +{ + pid_t pid = spc_fork(); + if (pid) //If fork failed, or we are the parent + { + MouseX = 0; + MouseY = 0; + return; + } + + //We are now the child proccess + + //If any of these LaunchBrowser() calls return that means it failed and we should try the next one + LaunchBrowser("mozilla"); + LaunchBrowser("mozilla-firefox"); + LaunchBrowser("konqueror"); + LaunchBrowser("lynx"); + + exit(0); //All browser launches failed, oh well +}