1 /* $NetBSD: pcnfsd_misc.c,v 1.11 2008/09/30 05:20:42 dholland Exp $ */
3 /* RE_SID: @(%)/usr/dosnfs/shades_SCCS/unix/pcnfsd/v2/src/SCCS/s.pcnfsd_misc.c 1.5 92/01/24 19:59:13 SMI */
5 **=====================================================================
6 ** Copyright (c) 1986,1987,1988,1989,1990,1991 by Sun Microsystems, Inc.
7 ** @(#)pcnfsd_misc.c 1.5 1/24/92
8 **=====================================================================
11 **=====================================================================
12 ** I N C L U D E F I L E S E C T I O N *
14 ** If your port requires different include files, add a suitable *
15 ** #define in the customization section, and make the inclusion or *
16 ** exclusion of the files conditional on this. *
17 **=====================================================================
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
42 #include <sys/fcntl.h>
58 **---------------------------------------------------------------------
60 **---------------------------------------------------------------------
67 char *mapfont
__P((char, char, char));
68 void myhandler
__P((int));
69 void start_watchdog
__P((int));
70 void stop_watchdog
__P((void));
73 **=====================================================================
74 ** C O D E S E C T I O N *
75 **=====================================================================
78 **---------------------------------------------------------------------
80 **---------------------------------------------------------------------
90 *s2
++ = (*s1
^ zchar
) & 0x7f;
103 static struct passwd localp
;
104 __aconst
char *pswd
, *ushell
;
107 #ifdef SHADOW_SUPPORT
112 #ifdef SHADOW_SUPPORT
114 **--------------------------------------------------------------
115 ** Check the existence of SHADOW. If it is there, then we are
116 ** running a two-password-file system.
117 **--------------------------------------------------------------
119 if (access(SHADOW
, 0))
120 shadowfile
= 0; /* SHADOW is not there */
126 (void) setspent(); /* Setting the shadow password file */
127 if ((p
= getpwnam(usrnam
)) == (struct passwd
*) NULL
||
128 (shadowfile
&& (sp
= getspnam(usrnam
)) == (struct spwd
*) NULL
))
129 return ((struct passwd
*) NULL
);
138 p
= getpwnam(usrnam
);
139 if (p
== (struct passwd
*) NULL
)
140 return ((struct passwd
*) NULL
);
145 /* *----------------------------------------------------------- * We
146 * may have an 'x' in which case look in /etc/shadow ..
147 * *----------------------------------------------------------- */
148 if (((strlen(pswd
)) == 1) && pswd
[0] == 'x') {
149 struct spwd
*shadow
= getspnam(usrnam
);
152 return ((struct passwd
*) NULL
);
153 pswd
= shadow
->sp_pwdp
;
157 localp
.pw_passwd
= pswd
;
158 #ifdef USE_GETUSERSHELL
161 while (ushell
= getusershell()) {
162 if (!strcmp(ushell
, localp
.pw_shell
)) {
169 return ((struct passwd
*) NULL
);
172 * the best we can do is to ensure that the shell ends in "sh"
174 ushell
= localp
.pw_shell
;
175 if (strlen(ushell
) < 2)
176 return ((struct passwd
*) NULL
);
177 ushell
+= strlen(ushell
) - 2;
178 if (strcmp(ushell
, "sh"))
179 return ((struct passwd
*) NULL
);
188 **---------------------------------------------------------------------
189 ** Print support procedures
190 **---------------------------------------------------------------------
195 mapfont(char f
, char i
, char b
)
197 static char fontname
[64];
199 fontname
[0] = 0; /* clear it out */
203 (void) strlcpy(fontname
, "Courier", sizeof(fontname
));
206 (void) strlcpy(fontname
, "Helvetica", sizeof(fontname
));
209 (void) strlcpy(fontname
, "Times", sizeof(fontname
));
212 (void) strlcpy(fontname
, "Times-Roman", sizeof(fontname
));
215 if (i
!= 'o' && b
!= 'b') { /* no bold or oblique */
216 if (f
== 't') /* special case Times */
217 (void) strlcat(fontname
, "-Roman", sizeof(fontname
));
220 (void) strlcat(fontname
, "-", sizeof(fontname
));
222 (void) strlcat(fontname
, "Bold", sizeof(fontname
));
223 if (i
== 'o') /* o-blique */
224 (void) strlcat(fontname
, f
== 't' ? "Italic" : "Oblique",
227 finis
: return (&fontname
[0]);
230 * run_ps630 performs the Diablo 630 emulation filtering process. ps630
231 * was broken in certain Sun releases: it would not accept point size or
232 * font changes. If your version is fixed, undefine the symbol
233 * PS630_IS_BROKEN and rebuild pc-nfsd.
235 /* #define PS630_IS_BROKEN 1 */
246 (void) strlcpy(temp_file
, f
, sizeof(temp_file
));
247 (void) strlcat(temp_file
, "X", sizeof(temp_file
)); /* intermediate file name */
249 #ifndef PS630_IS_BROKEN
250 (void) snprintf(commbuf
, sizeof(commbuf
), "ps630 -s %c%c -p %s -f ",
251 opts
[2], opts
[3], temp_file
);
252 (void) strlcat(commbuf
, mapfont(opts
[4], opts
[5], opts
[6]),
254 (void) strlcat(commbuf
, " -F ", sizeof(commbuf
));
255 (void) strlcat(commbuf
, mapfont(opts
[7], opts
[8], opts
[9]),
257 (void) strlcat(commbuf
, " ", sizeof(commbuf
));
258 (void) strlcat(commbuf
, f
, sizeof(commbuf
));
259 #else /* PS630_IS_BROKEN */
261 * The pitch and font features of ps630 appear to be broken at
264 (void) snprintf(commbuf
, sizeof(commbuf
), "ps630 -p %s %s",
266 #endif /* PS630_IS_BROKEN */
269 if ((i
= system(commbuf
)) != 0) {
271 * Under (un)certain conditions, ps630 may return -1 even
272 * if it worked. Hence the commenting out of this error
275 /* (void)fprintf(stderr, "\n\nrun_ps630 rc = %d\n", i) */ ;
278 if (rename(temp_file
, f
)) {
279 perror("run_ps630: rename");
290 **---------------------------------------------------------------------
291 ** WTMP update support
292 **---------------------------------------------------------------------
302 struct sockaddr_in
*who
;
309 /* Get network address of client. */
310 who
= &req
->rq_xprt
->xp_raddr
;
312 /* Get name of connected client */
313 hp
= gethostbyaddr((char *) &who
->sin_addr
,
314 sizeof(struct in_addr
),
320 host
= inet_ntoa(who
->sin_addr
);
324 logwtmp("PC-NFS", name
, host
);
327 logwtmpx("PC-NFS", name
, host
, 0, USER_PROCESS
);
334 **---------------------------------------------------------------------
335 ** Run-process-as-user procedures
336 **---------------------------------------------------------------------
343 static int child_pid
;
345 static char cached_user
[64] = "";
346 static uid_t cached_uid
;
347 static gid_t cached_gid
;
349 static struct sigaction old_action
;
350 static struct sigaction new_action
;
351 static struct itimerval timer
;
354 static FILE *pipe_handle
;
362 kill(child_pid
, SIGKILL
);
363 msg_out("rpc.pcnfsd: su_popen timeout - killed child process");
371 * Setup SIGALRM handler, force interrupt of ongoing syscall
374 new_action
.sa_handler
= myhandler
;
375 sigemptyset(&(new_action
.sa_mask
));
376 new_action
.sa_flags
= 0;
378 new_action
.sa_flags
|= SA_INTERRUPT
;
380 sigaction(SIGALRM
, &new_action
, &old_action
);
383 * Set interval timer for n seconds
385 timer
.it_interval
.tv_sec
= 0;
386 timer
.it_interval
.tv_usec
= 0;
387 timer
.it_value
.tv_sec
= n
;
388 timer
.it_value
.tv_usec
= 0;
389 setitimer(ITIMER_REAL
, &timer
, NULL
);
401 timer
.it_interval
.tv_sec
= 0;
402 timer
.it_interval
.tv_usec
= 0;
403 timer
.it_value
.tv_sec
= 0;
404 timer
.it_value
.tv_usec
= 0;
405 setitimer(ITIMER_REAL
, &timer
, NULL
);
408 * restore old signal handling
410 sigaction(SIGALRM
, &old_action
, NULL
);
414 su_popen(user
, cmd
, maxtime
)
420 int parent_fd
, child_fd
, pid
;
423 if (strcmp(cached_user
, user
)) {
426 pw
= getpwnam("nobody");
428 cached_uid
= pw
->pw_uid
;
429 cached_gid
= pw
->pw_gid
;
430 strlcpy(cached_user
, user
, sizeof(cached_user
));
432 cached_uid
= (uid_t
) (-2);
433 cached_gid
= (gid_t
) (-2);
434 cached_user
[0] = '\0';
438 msg_out("rpc.pcnfsd: unable to create pipe in su_popen");
441 parent_fd
= p
[READER_FD
];
442 child_fd
= p
[WRITER_FD
];
443 if ((pid
= fork()) == 0) {
446 for (i
= 0; i
< 10; i
++)
450 (void) dup2(child_fd
, 1);
451 (void) close(child_fd
);
453 dup2(1, 2); /* let's get stderr as well */
455 (void) setgid(cached_gid
);
456 (void) setuid(cached_uid
);
458 (void) execl("/bin/sh", "sh", "-c", cmd
, (char *) NULL
);
462 msg_out("rpc.pcnfsd: fork failed");
469 start_watchdog(maxtime
);
470 pipe_handle
= fdopen(parent_fd
, "r");
471 return (pipe_handle
);
485 while ((pid
= wait(&status
)) != child_pid
&& pid
!= -1);
486 return (pid
== -1 ? -1 : status
);
492 ** The following routine reads a file "/etc/pcnfsd.conf" if present,
493 ** and uses it to replace certain builtin elements, like the
494 ** name of the print spool directory. The configuration file
495 ** Is the usual kind: Comments begin with '#', blank lines are ignored,
496 ** and valid lines are of the form
498 ** <keyword><whitespace><value>
500 ** The following keywords are recognized:
503 ** printer name alias-for command
507 config_from_file(void)
517 if ((fd
= fopen("/etc/pcnfsd.conf", "r")) == NULL
)
519 while (fgets(buff
, 1024, fd
)) {
520 cp
= strchr(buff
, '\n');
522 cp
= strchr(buff
, '#');
525 kw
= strtok(buff
, " \t");
528 val
= strtok(NULL
, " \t");
531 if (!strcasecmp(kw
, "spooldir")) {
532 strlcpy(sp_name
, val
, sizeof(sp_name
));
536 if (!strcasecmp(kw
, "wtmp")) {
537 /* assume default is YES, just look for negatives */
538 if (!strcasecmp(val
, "no") ||
539 !strcasecmp(val
, "off") ||
540 !strcasecmp(val
, "disable") ||
546 if (!strcasecmp(kw
, "printer")) {
547 arg1
= strtok(NULL
, " \t");
548 arg2
= strtok(NULL
, "");
549 (void) add_printer_alias(val
, arg1
, arg2
);
553 ** Add new cases here
560 ** hack for main() - call config_from_file() then the real main
561 ** in the rpcgen output, which is hacked by CPPFLAGS to be "mymain"
565 int mymain(int argc
, char *argv
[]);
568 main(int argc
, char *argv
[])
571 return mymain(argc
, argv
);
575 ** strembedded - returns true if s1 is embedded (in any case) in s2
584 if (!strcasecmp(s1
, s2
))