Expand PMF_FN_* macros.
[netbsd-mini2440.git] / usr.sbin / rpc.pcnfsd / pcnfsd_misc.c
blob93a2f8d87fc8587b5dd334d899221724cf7264f6
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 */
4 /*
5 **=====================================================================
6 ** Copyright (c) 1986,1987,1988,1989,1990,1991 by Sun Microsystems, Inc.
7 ** @(#)pcnfsd_misc.c 1.5 1/24/92
8 **=====================================================================
9 */
11 **=====================================================================
12 ** I N C L U D E F I L E S E C T I O N *
13 ** *
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 **=====================================================================
20 #include <sys/file.h>
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <sys/wait.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <netdb.h>
33 #include <pwd.h>
34 #include <signal.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <util.h>
41 #ifdef ISC_2_0
42 #include <sys/fcntl.h>
43 #endif
45 #ifdef SHADOW_SUPPORT
46 #include <shadow.h>
47 #endif
49 #ifdef WTMP
50 int wtmp_enabled = 1;
51 #endif
53 #include "common.h"
54 #include "pcnfsd.h"
55 #include "extern.h"
58 **---------------------------------------------------------------------
59 ** Other #define's
60 **---------------------------------------------------------------------
63 #define zchar 0x5b
65 char tempstr[256];
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 **---------------------------------------------------------------------
79 ** Support procedures
80 **---------------------------------------------------------------------
84 void
85 scramble(s1, s2)
86 char *s1;
87 char *s2;
89 while (*s1) {
90 *s2++ = (*s1 ^ zchar) & 0x7f;
91 s1++;
93 *s2 = 0;
98 struct passwd *
99 get_password(usrnam)
100 char *usrnam;
102 struct passwd *p;
103 static struct passwd localp;
104 __aconst char *pswd, *ushell;
107 #ifdef SHADOW_SUPPORT
108 struct spwd *sp;
109 int shadowfile;
110 #endif
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 */
121 else
122 shadowfile = 1;
124 setpwent();
125 if (shadowfile)
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);
131 if (shadowfile) {
132 pswd = sp->sp_pwdp;
133 (void) endspent();
134 } else
135 pswd = p->pw_passwd;
137 #else
138 p = getpwnam(usrnam);
139 if (p == (struct passwd *) NULL)
140 return ((struct passwd *) NULL);
141 pswd = p->pw_passwd;
142 #endif
144 #ifdef ISC_2_0
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);
151 if (!shadow)
152 return ((struct passwd *) NULL);
153 pswd = shadow->sp_pwdp;
155 #endif
156 localp = *p;
157 localp.pw_passwd = pswd;
158 #ifdef USE_GETUSERSHELL
160 setusershell();
161 while (ushell = getusershell()) {
162 if (!strcmp(ushell, localp.pw_shell)) {
163 ok = 1;
164 break;
167 endusershell();
168 if (!ok)
169 return ((struct passwd *) NULL);
170 #else
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);
181 #endif
182 return (&localp);
188 **---------------------------------------------------------------------
189 ** Print support procedures
190 **---------------------------------------------------------------------
194 char *
195 mapfont(char f, char i, char b)
197 static char fontname[64];
199 fontname[0] = 0; /* clear it out */
201 switch (f) {
202 case 'c':
203 (void) strlcpy(fontname, "Courier", sizeof(fontname));
204 break;
205 case 'h':
206 (void) strlcpy(fontname, "Helvetica", sizeof(fontname));
207 break;
208 case 't':
209 (void) strlcpy(fontname, "Times", sizeof(fontname));
210 break;
211 default:
212 (void) strlcpy(fontname, "Times-Roman", sizeof(fontname));
213 goto finis;
215 if (i != 'o' && b != 'b') { /* no bold or oblique */
216 if (f == 't') /* special case Times */
217 (void) strlcat(fontname, "-Roman", sizeof(fontname));
218 goto finis;
220 (void) strlcat(fontname, "-", sizeof(fontname));
221 if (b == 'b')
222 (void) strlcat(fontname, "Bold", sizeof(fontname));
223 if (i == 'o') /* o-blique */
224 (void) strlcat(fontname, f == 't' ? "Italic" : "Oblique",
225 sizeof(fontname));
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 */
237 void
238 run_ps630(f, opts)
239 char *f;
240 char *opts;
242 char temp_file[256];
243 char commbuf[256];
244 int i;
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]),
253 sizeof(commbuf));
254 (void) strlcat(commbuf, " -F ", sizeof(commbuf));
255 (void) strlcat(commbuf, mapfont(opts[7], opts[8], opts[9]),
256 sizeof(commbuf));
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
262 * this time.
264 (void) snprintf(commbuf, sizeof(commbuf), "ps630 -p %s %s",
265 temp_file, f);
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
273 * report.
275 /* (void)fprintf(stderr, "\n\nrun_ps630 rc = %d\n", i) */ ;
276 /* exit(1); */
278 if (rename(temp_file, f)) {
279 perror("run_ps630: rename");
280 exit(1);
282 return;
290 **---------------------------------------------------------------------
291 ** WTMP update support
292 **---------------------------------------------------------------------
296 #ifdef WTMP
297 void
298 wlogin(name, req)
299 char *name;
300 struct svc_req *req;
302 struct sockaddr_in *who;
303 struct hostent *hp;
304 char *host;
306 if (!wtmp_enabled)
307 return;
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),
315 who->sin_family);
317 if (hp) {
318 host = hp->h_name;
319 } else {
320 host = inet_ntoa(who->sin_addr);
323 #ifdef SUPPORT_UTMP
324 logwtmp("PC-NFS", name, host);
325 #endif
326 #ifdef SUPPORT_UTMPX
327 logwtmpx("PC-NFS", name, host, 0, USER_PROCESS);
328 #endif
330 #endif /* WTMP */
334 **---------------------------------------------------------------------
335 ** Run-process-as-user procedures
336 **---------------------------------------------------------------------
340 #define READER_FD 0
341 #define WRITER_FD 1
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;
353 int interrupted = 0;
354 static FILE *pipe_handle;
356 void
357 myhandler(dummy)
358 int dummy;
360 interrupted = 1;
361 fclose(pipe_handle);
362 kill(child_pid, SIGKILL);
363 msg_out("rpc.pcnfsd: su_popen timeout - killed child process");
366 void
367 start_watchdog(n)
368 int n;
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;
377 #ifdef SA_INTERRUPT
378 new_action.sa_flags |= SA_INTERRUPT;
379 #endif
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);
390 interrupted = 0;
394 void
395 stop_watchdog()
398 * Cancel timer
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);
413 FILE *
414 su_popen(user, cmd, maxtime)
415 char *user;
416 char *cmd;
417 int maxtime;
419 int p[2];
420 int parent_fd, child_fd, pid;
421 struct passwd *pw;
423 if (strcmp(cached_user, user)) {
424 pw = getpwnam(user);
425 if (!pw)
426 pw = getpwnam("nobody");
427 if (pw) {
428 cached_uid = pw->pw_uid;
429 cached_gid = pw->pw_gid;
430 strlcpy(cached_user, user, sizeof(cached_user));
431 } else {
432 cached_uid = (uid_t) (-2);
433 cached_gid = (gid_t) (-2);
434 cached_user[0] = '\0';
437 if (pipe(p) < 0) {
438 msg_out("rpc.pcnfsd: unable to create pipe in su_popen");
439 return (NULL);
441 parent_fd = p[READER_FD];
442 child_fd = p[WRITER_FD];
443 if ((pid = fork()) == 0) {
444 int i;
446 for (i = 0; i < 10; i++)
447 if (i != child_fd)
448 (void) close(i);
449 if (child_fd != 1) {
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);
459 _exit(255);
461 if (pid == -1) {
462 msg_out("rpc.pcnfsd: fork failed");
463 close(parent_fd);
464 close(child_fd);
465 return (NULL);
467 child_pid = pid;
468 close(child_fd);
469 start_watchdog(maxtime);
470 pipe_handle = fdopen(parent_fd, "r");
471 return (pipe_handle);
475 su_pclose(ptr)
476 FILE *ptr;
478 int pid, status;
480 stop_watchdog();
482 fclose(ptr);
483 if (child_pid == -1)
484 return (-1);
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:
502 ** spooldir
503 ** printer name alias-for command
504 ** wtmp yes|no
506 static void
507 config_from_file(void)
509 FILE *fd;
510 char buff[1024];
511 char *cp;
512 char *kw;
513 char *val;
514 char *arg1;
515 char *arg2;
517 if ((fd = fopen("/etc/pcnfsd.conf", "r")) == NULL)
518 return;
519 while (fgets(buff, 1024, fd)) {
520 cp = strchr(buff, '\n');
521 *cp = '\0';
522 cp = strchr(buff, '#');
523 if (cp)
524 *cp = '\0';
525 kw = strtok(buff, " \t");
526 if (kw == NULL)
527 continue;
528 val = strtok(NULL, " \t");
529 if (val == NULL)
530 continue;
531 if (!strcasecmp(kw, "spooldir")) {
532 strlcpy(sp_name, val, sizeof(sp_name));
533 continue;
535 #ifdef WTMP
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") ||
541 !strcmp(val, "0"))
542 wtmp_enabled = 0;
543 continue;
545 #endif
546 if (!strcasecmp(kw, "printer")) {
547 arg1 = strtok(NULL, " \t");
548 arg2 = strtok(NULL, "");
549 (void) add_printer_alias(val, arg1, arg2);
550 continue;
553 ** Add new cases here
556 fclose(fd);
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"
563 #undef main
565 int mymain(int argc, char *argv[]);
568 main(int argc, char *argv[])
570 config_from_file();
571 return mymain(argc, argv);
575 ** strembedded - returns true if s1 is embedded (in any case) in s2
579 strembedded(s1, s2)
580 const char *s1;
581 const char *s2;
583 while (*s2) {
584 if (!strcasecmp(s1, s2))
585 return 1;
586 s2++;
588 return 0;