#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#ifdef SUPPORT_UTMPX
#include <utmpx.h>
#endif
#ifdef ISC_2_0
#include <sys/fcntl.h>
#endif
#ifdef SHADOW_SUPPORT
#include <shadow.h>
#endif
#ifdef WTMP
int wtmp_enabled = 1;
#endif
#include "common.h"
#include "pcnfsd.h"
#include "extern.h"
#define zchar 0x5b
char *mapfont(char, char, char);
void myhandler(int);
void start_watchdog(int);
void stop_watchdog(void);
void
scramble(char *s1, char *s2)
{
while (*s1) {
*s2++ = (*s1 ^ zchar) & 0x7f;
s1++;
}
*s2 = 0;
}
struct passwd *
get_password(char *usrnam)
{
struct passwd *p;
static struct passwd localp;
__aconst char *pswd, *ushell;
#ifdef SHADOW_SUPPORT
struct spwd *sp;
int shadowfile;
#endif
#ifdef SHADOW_SUPPORT
if (access(SHADOW, 0))
shadowfile = 0;
else
shadowfile = 1;
setpwent();
if (shadowfile)
(void) setspent();
if ((p = getpwnam(usrnam)) == NULL ||
(shadowfile && (sp = getspnam(usrnam)) == NULL))
return (NULL);
if (shadowfile) {
pswd = sp->sp_pwdp;
(void) endspent();
} else
pswd = p->pw_passwd;
#else
p = getpwnam(usrnam);
if (p == NULL)
return (NULL);
pswd = p->pw_passwd;
#endif
#ifdef ISC_2_0
if (((strlen(pswd)) == 1) && pswd[0] == 'x') {
struct spwd *shadow = getspnam(usrnam);
if (!shadow)
return (NULL);
pswd = shadow->sp_pwdp;
}
#endif
localp = *p;
localp.pw_passwd = pswd;
#ifdef USE_GETUSERSHELL
setusershell();
while (ushell = getusershell()) {
if (!strcmp(ushell, localp.pw_shell)) {
ok = 1;
break;
}
}
endusershell();
if (!ok)
return (NULL);
#else
ushell = localp.pw_shell;
if (strlen(ushell) < 2)
return (NULL);
ushell += strlen(ushell) - 2;
if (strcmp(ushell, "sh"))
return (NULL);
#endif
return (&localp);
}
char *
mapfont(char f, char i, char b)
{
static char fontname[64];
fontname[0] = 0;
switch (f) {
case 'c':
(void) strlcpy(fontname, "Courier", sizeof(fontname));
break;
case 'h':
(void) strlcpy(fontname, "Helvetica", sizeof(fontname));
break;
case 't':
(void) strlcpy(fontname, "Times", sizeof(fontname));
break;
default:
(void) strlcpy(fontname, "Times-Roman", sizeof(fontname));
goto finis;
}
if (i != 'o' && b != 'b') {
if (f == 't')
(void) strlcat(fontname, "-Roman", sizeof(fontname));
goto finis;
}
(void) strlcat(fontname, "-", sizeof(fontname));
if (b == 'b')
(void) strlcat(fontname, "Bold", sizeof(fontname));
if (i == 'o')
(void) strlcat(fontname, f == 't' ? "Italic" : "Oblique",
sizeof(fontname));
finis: return (&fontname[0]);
}
void
run_ps630(char *f, char *opts)
{
char temp_file[256];
char commbuf[256];
int i;
(void) strlcpy(temp_file, f, sizeof(temp_file));
(void) strlcat(temp_file, "X", sizeof(temp_file));
#ifndef PS630_IS_BROKEN
(void) snprintf(commbuf, sizeof(commbuf), "ps630 -s %c%c -p %s -f ",
opts[2], opts[3], temp_file);
(void) strlcat(commbuf, mapfont(opts[4], opts[5], opts[6]),
sizeof(commbuf));
(void) strlcat(commbuf, " -F ", sizeof(commbuf));
(void) strlcat(commbuf, mapfont(opts[7], opts[8], opts[9]),
sizeof(commbuf));
(void) strlcat(commbuf, " ", sizeof(commbuf));
(void) strlcat(commbuf, f, sizeof(commbuf));
#else
(void) snprintf(commbuf, sizeof(commbuf), "ps630 -p %s %s",
temp_file, f);
#endif
if ((i = system(commbuf)) != 0) {
;
}
if (rename(temp_file, f)) {
perror("run_ps630: rename");
exit(1);
}
return;
}
#ifdef WTMP
void
wlogin(char *name, struct svc_req *req)
{
struct sockaddr_in *who;
struct hostent *hp;
char *host;
if (!wtmp_enabled)
return;
who = &req->rq_xprt->xp_raddr;
hp = gethostbyaddr((char *) &who->sin_addr,
sizeof(struct in_addr),
who->sin_family);
if (hp) {
host = hp->h_name;
} else {
host = inet_ntoa(who->sin_addr);
}
#ifdef SUPPORT_UTMP
logwtmp("PC-NFS", name, host);
#endif
#ifdef SUPPORT_UTMPX
logwtmpx("PC-NFS", name, host, 0, USER_PROCESS);
#endif
}
#endif
#define READER_FD 0
#define WRITER_FD 1
static int child_pid;
static char cached_user[64] = "";
static uid_t cached_uid;
static gid_t cached_gid;
static struct sigaction old_action;
static struct sigaction new_action;
static struct itimerval timer;
int interrupted = 0;
static FILE *pipe_handle;
void
myhandler(int dummy)
{
interrupted = 1;
fclose(pipe_handle);
kill(child_pid, SIGKILL);
msg_out("rpc.pcnfsd: su_popen timeout - killed child process");
}
void
start_watchdog(int n)
{
new_action.sa_handler = myhandler;
sigemptyset(&(new_action.sa_mask));
new_action.sa_flags = 0;
#ifdef SA_INTERRUPT
new_action.sa_flags |= SA_INTERRUPT;
#endif
sigaction(SIGALRM, &new_action, &old_action);
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_value.tv_sec = n;
timer.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
interrupted = 0;
}
void
stop_watchdog()
{
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
sigaction(SIGALRM, &old_action, NULL);
}
FILE *
su_popen(char *user, char *cmd, int maxtime)
{
int p[2];
int parent_fd, child_fd, pid;
struct passwd *pw;
if (strcmp(cached_user, user)) {
pw = getpwnam(user);
if (!pw)
pw = getpwnam("nobody");
if (pw) {
cached_uid = pw->pw_uid;
cached_gid = pw->pw_gid;
strlcpy(cached_user, user, sizeof(cached_user));
} else {
cached_uid = (uid_t) (-2);
cached_gid = (gid_t) (-2);
cached_user[0] = '\0';
}
}
if (pipe(p) < 0) {
msg_out("rpc.pcnfsd: unable to create pipe in su_popen");
return (NULL);
}
parent_fd = p[READER_FD];
child_fd = p[WRITER_FD];
if ((pid = fork()) == 0) {
int i;
for (i = 0; i < 10; i++)
if (i != child_fd)
(void) close(i);
if (child_fd != 1) {
(void) dup2(child_fd, 1);
(void) close(child_fd);
}
dup2(1, 2);
(void) setgid(cached_gid);
(void) setuid(cached_uid);
(void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
_exit(255);
}
if (pid == -1) {
msg_out("rpc.pcnfsd: fork failed");
close(parent_fd);
close(child_fd);
return (NULL);
}
child_pid = pid;
close(child_fd);
start_watchdog(maxtime);
pipe_handle = fdopen(parent_fd, "r");
return (pipe_handle);
}
int
su_pclose(FILE *ptr)
{
int pid, status;
stop_watchdog();
fclose(ptr);
if (child_pid == -1)
return (-1);
while ((pid = wait(&status)) != child_pid && pid != -1);
return (pid == -1 ? -1 : status);
}
static void
config_from_file(void)
{
FILE *fd;
char buff[1024];
char *cp;
char *kw;
char *val;
char *arg1;
char *arg2;
if ((fd = fopen("/etc/pcnfsd.conf", "r")) == NULL)
return;
while (fgets(buff, 1024, fd)) {
cp = strchr(buff, '\n');
*cp = '\0';
cp = strchr(buff, '#');
if (cp)
*cp = '\0';
kw = strtok(buff, " \t");
if (kw == NULL)
continue;
val = strtok(NULL, " \t");
if (val == NULL)
continue;
if (!strcasecmp(kw, "spooldir")) {
strlcpy(sp_name, val, sizeof(sp_name));
continue;
}
#ifdef WTMP
if (!strcasecmp(kw, "wtmp")) {
if (!strcasecmp(val, "no") ||
!strcasecmp(val, "off") ||
!strcasecmp(val, "disable") ||
!strcmp(val, "0"))
wtmp_enabled = 0;
continue;
}
#endif
if (!strcasecmp(kw, "printer")) {
arg1 = strtok(NULL, " \t");
arg2 = strtok(NULL, "");
(void) add_printer_alias(val, arg1, arg2);
continue;
}
}
fclose(fd);
}
#undef main
int mymain(int argc, char *argv[]);
int
main(int argc, char *argv[])
{
config_from_file();
return mymain(argc, argv);
}
int
strembedded(const char *s1, const char *s2)
{
while (*s2) {
if (!strcasecmp(s1, s2))
return 1;
s2++;
}
return 0;
}