//Solaris and AIX should have this DWORD CTGetPidOfCmdLine( PCSTR programName, PCSTR programFilename, PCSTR cmdLine, uid_t owner, pid_t *pid, size_t *count ) { DWORD ceError = ERROR_NOT_SUPPORTED; size_t fillCount = 0; size_t foundCount = 0; struct stat findStat; DIR *dir = NULL; struct dirent *dirEntry = NULL; PSTR filePath = NULL; struct psinfo infoStruct; FILE *infoFile = NULL; struct stat compareStat; BOOLEAN bFileExists; #if defined(__LWI_SOLARIS__) int (*getzoneid)() = NULL; int zoneid = -1; #endif if(count) { fillCount = *count; *count = 0; } else if(pid != NULL) fillCount = 1; if(programFilename != NULL) { while(stat(programFilename, &findStat) < 0) { if(errno == EINTR) continue; GCE(ceError = LwMapErrnoToLwError(errno)); } } if ((dir = opendir("/proc")) == NULL) { GCE(ceError = LwMapErrnoToLwError(errno)); } #if defined(__LWI_SOLARIS__) getzoneid = dlsym(RTLD_DEFAULT, "getzoneid"); if (getzoneid) { zoneid = getzoneid(); } #endif while(1) { errno = 0; dirEntry = readdir(dir); if(dirEntry == NULL) { if(errno != 0) GCE(ceError = LwMapErrnoToLwError(errno)); else { //No error here. We simply read the last entry break; } } if(dirEntry->d_name[0] == '.') continue; // On AIX, there is a /proc/sys which does not contain a psinfo if(!isdigit((int)dirEntry->d_name[0])) continue; CT_SAFE_FREE_STRING(filePath); GCE(ceError = CTAllocateStringPrintf(&filePath, "/proc/%s/psinfo", dirEntry->d_name)); GCE(ceError = CTCheckFileOrLinkExists(filePath, &bFileExists)); if(!bFileExists) { // On AIX 6.1, a defunct process can lack a psinfo file. continue; } GCE(ceError = CTSafeCloseFile(&infoFile)); GCE(ceError = CTOpenFile(filePath, "r", &infoFile)); if(fread(&infoStruct, sizeof(infoStruct), 1, infoFile) != 1) { GCE(ceError = LwMapErrnoToLwError(errno)); } #if defined(__LWI_SOLARIS__) if (zoneid != -1) { int processzoneid = -1; #ifdef HAVE_STRUCT_PSINFO_PR_ZONEID processzoneid = (int) infoStruct.pr_zoneid; #else processzoneid = (int) *(infoStruct.pr_filler + sizeof(infoStruct.pr_filler)/sizeof(infoStruct.pr_filler[0]) - 3); #endif if (zoneid != processzoneid) { continue; } } #endif if (owner != (uid_t)-1 && owner != infoStruct.pr_euid) { continue; } if (programName != NULL && strcmp(infoStruct.pr_fname, programName)) { continue; } if (cmdLine != NULL && strcmp(infoStruct.pr_psargs, cmdLine)) { continue; } if(programFilename != NULL) { CT_SAFE_FREE_STRING(filePath); GCE(ceError = CTAllocateStringPrintf(&filePath, "/proc/%s/object/a.out", dirEntry->d_name)); while(stat(filePath, &compareStat) < 0) { if(errno == EINTR) continue; if(errno == ENOENT || errno == ENOTDIR) { //This process wasn't executed from a file? goto not_match; } GCE(ceError = LwMapErrnoToLwError(errno)); } if(findStat.st_ino != compareStat.st_ino) continue; if(findStat.st_dev != compareStat.st_dev) continue; if(findStat.st_rdev != compareStat.st_rdev) continue; } //This is a match if(foundCount < fillCount) pid[foundCount] = infoStruct.pr_pid; foundCount++; not_match: ; } if(count) *count = foundCount; else if(!ceError && foundCount == 0) ceError = ERROR_PROC_NOT_FOUND; cleanup: if(dir != NULL) closedir(dir); CT_SAFE_FREE_STRING(filePath); CTSafeCloseFile(&infoFile); return ceError; }
int uadmin(int cmd, int fcn, uintptr_t mdep) { extern int __uadmin(int cmd, int fcn, uintptr_t mdep); char *bargs, cmdbuf[256]; struct stat sbuf; char *altroot; bargs = (char *)mdep; if (geteuid() == 0 && getzoneid() == GLOBAL_ZONEID && (cmd == A_SHUTDOWN || cmd == A_REBOOT)) { int off = 0; switch (fcn) { case AD_IBOOT: case AD_SBOOT: case AD_SIBOOT: /* * These functions fabricate appropriate bootargs. * If bootargs are passed in, map these functions * to AD_BOOT. */ if (bargs == 0) { switch (fcn) { case AD_IBOOT: bargs = "-a"; break; case AD_SBOOT: bargs = "-s"; break; case AD_SIBOOT: bargs = "-sa"; break; } } /*FALLTHROUGH*/ case AD_BOOT: case AD_FASTREBOOT: if (bargs == 0) break; /* no args */ if (legal_arg(bargs) < 0) break; /* bad args */ /* avoid cancellation in system() */ (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); /* check for /stubboot */ if (stat("/stubboot/boot/grub/menu.lst", &sbuf) == 0) { altroot = "-R /stubboot "; } else { altroot = ""; } if (fcn == AD_FASTREBOOT) { char *newarg, *head; char bargs_scratch[BOOTARGS_MAX]; bzero(bargs_scratch, BOOTARGS_MAX); bcopy(bargs, bargs_scratch, strlen(bargs)); head = bargs_scratch; newarg = strtok(bargs_scratch, " "); if (newarg == NULL || newarg[0] == '-') break; /* First argument is rootdir */ if (strncmp(&newarg[strlen(newarg)-4], "unix", 4) != 0) { newarg = strtok(NULL, " "); off = newarg - head; } /* * If we are using alternate root via * mountpoint or a different BE, don't * bother to update the temp menu entry. */ if (off > 0) break; } /* are we rebooting to a GRUB menu entry? */ if (isdigit(bargs[0])) { int entry = strtol(bargs, NULL, 10); (void) snprintf(cmdbuf, sizeof (cmdbuf), "/sbin/bootadm set-menu %sdefault=%d", altroot, entry); } else { (void) snprintf(cmdbuf, sizeof (cmdbuf), "/sbin/bootadm -m update_temp %s" "-o %s%s%s", altroot, quote, &bargs[off], quote); } (void) system(cmdbuf); } check_archive_update(); } return (__uadmin(cmd, fcn, mdep)); }
/* * This routine is called from preenlib the first time. It is then * recursively called through preen_subdev. * * The argument passed in (uname) starts with the special device from * /etc/vfstab. Recursive calls pass in the underlying physical device * names. */ void preen_build_devs( char *uname, /* name of metadevice */ struct dk_cinfo *dkiop, /* associated controller info */ void *dp /* magic info */ ) { char *setname = NULL; char *tname = NULL; mdsetname_t *sp; mdname_t *namep; /* metadevice name */ mdnamelist_t *nlp = NULL; /* list of real devices */ mdnamelist_t *p; devid_nmlist_t *nm_list = NULL; md_error_t status = mdnullerror; md_error_t *ep = &status; int ep_valid = 0; /* does ep contain a real error */ struct stat statb; static int md_major = -1; side_t sideno; /* * The rest of the code in this library can't work within a * non-global zone so we just return the top level metadevice back * to be fscked. */ if (getzoneid() != GLOBAL_ZONEID) { preen_addunit(dp, dkiop->dki_dname, NULL, NULL, dkiop->dki_unit); return; } if (stat(uname, &statb) != 0) return; if (md_major == -1 && get_major_from_n2m(MD_MODULE, &md_major) != 0) return; /* * If the path passed in is not a metadevice, then add that * device to the list (preen_addunit) since it has to be a * physical device. */ if (major(statb.st_rdev) != md_major) { preen_addunit(dp, dkiop->dki_dname, NULL, NULL, dkiop->dki_unit); return; } /* * Bind to the cluster library */ if (sdssc_bind_library() == SDSSC_ERROR) return; if (md_init_daemon("fsck", ep) != 0) { ep_valid = 1; goto out; } /* * parse the path name to get the diskset name. */ parse_device(NULL, uname, &tname, &setname); Free(tname); if ((sp = metasetname(setname, ep)) == NULL) { ep_valid = 1; goto out; } /* check for ownership */ if (meta_check_ownership(sp, ep) != 0) { /* * Don't own the set but we are here implies * that this is a clustered proxy device. Simply add * the unit. */ preen_addunit(dp, dkiop->dki_dname, NULL, NULL, dkiop->dki_unit); ep_valid = 1; goto out; } /* * get list of underlying physical devices. */ if ((namep = metaname(&sp, uname, UNKNOWN, ep)) == NULL) { ep_valid = 1; goto out; } if (namep->dev == NODEV64) { goto out; } if (meta_getdevs(sp, namep, &nlp, ep) != 0) { ep_valid = 1; goto out; } if ((sideno = getmyside(sp, ep)) == MD_SIDEWILD) { ep_valid = 1; goto out; } /* gather and add the underlying devs */ for (p = nlp; (p != NULL); p = p->next) { mdname_t *devnp = p->namep; int fd; struct dk_cinfo cinfo; ddi_devid_t md_did; char *devname; char *minor_name = NULL; char mname[MAXPATHLEN]; /* * we don't want to use the rname anymore because * that may have changed. Use the device id information * to find the correct ctd name and open based on that. * If there isn't a devid or we have a did device, then * use the rname. In clustering, it's corrected for us. * If no devid it's at least worth a try. */ if (((md_did = meta_getdidbykey(sp->setno, sideno, devnp->key, ep)) == NULL) || ((minor_name = meta_getdidminorbykey(sp->setno, sideno, devnp->key, ep)) == NULL)) { devname = devnp->rname; if (md_did) Free(md_did); } else { if (strstr(minor_name, ",raw") == NULL) { (void) snprintf(mname, MAXPATHLEN, "%s,raw", minor_name); } else { (void) snprintf(mname, MAXPATHLEN, "%s", minor_name); } /* * We need to make sure we call this with a specific * mname (raw mname) so that we get the exact slice * with the given device id. Otherwise we could try * to open a slice that doesn't really exist. */ if (meta_deviceid_to_nmlist("/dev", md_did, mname, &nm_list) != 0) { (void) mdsyserror(ep, errno, devnp->rname); ep_valid = 1; Free(md_did); Free(minor_name); goto out; } devname = Strdup(nm_list->devname); Free(md_did); Free(minor_name); devid_free_nmlist(nm_list); } /* get device name and (real) cinfo */ if ((fd = open(devname, O_RDONLY, 0)) < 0) { (void) mdsyserror(ep, errno, devname); ep_valid = 1; /* * We need to scan all sub devices even if some fail * since exit here would end up in not finishing fsck * on all devices and prevent us from going into * multiuser mode. */ continue; } if (ioctl(fd, DKIOCINFO, &cinfo) != 0) { (void) mdsyserror(ep, errno, devname); (void) close(fd); ep_valid = 1; /* Continue here too. See comment from before */ continue; } (void) close(fd); /* sd/ssd bug */ /* * preen_subdev fails when the device name has been * resolved to the physical layer. Hence it is added * to preen_addunit. */ if (preen_subdev(devname, &cinfo, dp) != 0) { preen_addunit(dp, cinfo.dki_dname, NULL, NULL, cinfo.dki_unit); } } /* cleanup, if we fail, just add this composite device to the list */ out: if (setname != NULL) Free(setname); if (ep_valid != 0) { mde_perror(&status, ""); mdclrerror(&status); } metafreenamelist(nlp); }
int main(int argc, char *argv[]) { FILE *f; char *ptr, *start; struct passwd *pwd; char *term_name; int c; int aflag = 0; int errflg = 0; int zflg = 0; int Zflg = 0; char *zonename = NULL; zoneid_t *zoneidlist = NULL; uint_t nzids_saved, nzids = 0; (void) setlocale(LC_ALL, ""); while ((c = getopt(argc, argv, "g:az:Z")) != EOF) switch (c) { case 'a': aflag++; break; case 'g': if (gflag) { (void) fprintf(stderr, "Only one group allowed\n"); return (1); } if ((pgrp = getgrnam(grpname = optarg)) == NULL) { (void) fprintf(stderr, "Unknown group %s\n", grpname); return (1); } gflag++; break; case 'z': zflg++; zonename = optarg; if (getzoneidbyname(zonename) == -1) { (void) fprintf(stderr, "Specified zone %s " "is invalid", zonename); return (1); } break; case 'Z': Zflg++; break; case '?': errflg++; break; } if (errflg) { (void) fprintf(stderr, "Usage: wall [-a] [-g group] [-z zone] [-Z] [files...]\n"); return (1); } if (zflg && Zflg) { (void) fprintf(stderr, "Cannot use -z with -Z\n"); return (1); } if (optind < argc) infile = argv[optind]; if (uname(&utsn) == -1) { (void) fprintf(stderr, "wall: uname() failed, %s\n", strerror(errno)); return (2); } (void) strcpy(systm, utsn.nodename); /* * Get the name of the terminal wall is running from. */ if ((term_name = ttyname(fileno(stderr))) != NULL) { /* * skip the leading "/dev/" in term_name */ (void) strncpy(line, &term_name[5], sizeof (line) - 1); } if (who[0] == '?') { if (pwd = getpwuid(getuid())) (void) strncpy(&who[0], pwd->pw_name, sizeof (who)); } f = stdin; if (infile) { f = fopen(infile, "r"); if (f == NULL) { (void) fprintf(stderr, "Cannot open %s\n", infile); return (1); } } start = &mesg[0]; ptr = start; while ((ptr - start) < 3000) { size_t n; if (fgets(ptr, &mesg[sizeof (mesg)] - ptr, f) == NULL) break; if ((n = strlen(ptr)) == 0) break; ptr += n; } (void) fclose(f); /* * If the request is from the rwall daemon then use the caller's * name and host. We determine this if all of the following is true: * 1) First 5 characters are "From " * 2) Next non-white characters are of the form "name@host:" */ if (strcmp(line, "???") == 0) { char rwho[MAXNAMLEN+1]; char rsystm[MAXNAMLEN+1]; char *cp; if (strncmp(mesg, "From ", 5) == 0) { cp = &mesg[5]; cp = copy_str_till(rwho, cp, '@', MAXNAMLEN + 1); if (rwho[0] != '\0') { cp = copy_str_till(rsystm, ++cp, ':', MAXNAMLEN + 1); if (rsystm[0] != '\0') { (void) strcpy(systm, rsystm); (void) strncpy(rwho, who, sizeof (who)); (void) strcpy(line, "rpc.rwalld"); } } } } (void) time(&tloc); (void) strftime(time_buf, sizeof (time_buf), DATE_FMT, localtime(&tloc)); if (zflg != 0) { if ((zoneidlist = malloc(sizeof (zoneid_t))) == NULL || (*zoneidlist = getzoneidbyname(zonename)) == -1) return (errno); nzids = 1; } else if (Zflg != 0) { if (zone_list(NULL, &nzids) != 0) return (errno); again: nzids *= 2; if ((zoneidlist = malloc(nzids * sizeof (zoneid_t))) == NULL) exit(errno); nzids_saved = nzids; if (zone_list(zoneidlist, &nzids) != 0) { (void) free(zoneidlist); return (errno); } if (nzids > nzids_saved) { free(zoneidlist); goto again; } } if (zflg || Zflg) { for (; nzids > 0; --nzids) sendmes_tozone(zoneidlist[nzids-1], aflag); free(zoneidlist); } else sendmes_tozone(getzoneid(), aflag); return (0); }
/* * Note to future maintainers: with the change of wall to use the * getutxent() API, the forked children (created by this function) * must call _exit as opposed to exit. This is necessary to avoid * unwanted fflushing of getutxent's stdio stream (caused by atexit * processing). */ static void sendmes(struct utmpx *p, zoneid_t zid) { int i; char *s; static char device[LMAX + 6]; char *bp; int ibp; FILE *f; int fd, tmpl_fd; boolean_t zoneenter = B_FALSE; if (zid != getzoneid()) { zoneenter = B_TRUE; tmpl_fd = init_template(); if (tmpl_fd == -1) { (void) fprintf(stderr, "Could not initialize " "process contract"); return; } } while ((i = (int)fork()) == -1) { (void) alarm(60); (void) wait((int *)0); (void) alarm(0); } if (i) return; if (zoneenter && zone_enter(zid) == -1) { char zonename[ZONENAME_MAX]; (void) getzonenamebyid(zid, zonename, ZONENAME_MAX); (void) fprintf(stderr, "Could not enter zone " "%s\n", zonename); } if (zoneenter) (void) ct_tmpl_clear(tmpl_fd); if (gflag) if (!chkgrp(p->ut_user)) _exit(0); (void) signal(SIGHUP, SIG_IGN); (void) alarm(60); s = &device[0]; (void) snprintf(s, sizeof (device), "/dev/%.*s", LMAX, p->ut_line); /* check if the device is really a tty */ if ((fd = open(s, O_WRONLY|O_NOCTTY|O_NONBLOCK)) == -1) { (void) fprintf(stderr, "Cannot send to %.*s on %s\n", NMAX, p->ut_user, s); perror("open"); (void) fflush(stderr); _exit(1); } else { if (!isatty(fd)) { (void) fprintf(stderr, "Cannot send to device %.*s %s\n", LMAX, p->ut_line, "because it's not a tty"); openlog("wall", 0, LOG_AUTH); syslog(LOG_CRIT, "%.*s in utmpx is not a tty\n", LMAX, p->ut_line); closelog(); (void) fflush(stderr); _exit(1); } } #ifdef DEBUG (void) close(fd); f = fopen("wall.debug", "a"); #else f = fdopen(fd, "w"); #endif if (f == NULL) { (void) fprintf(stderr, "Cannot send to %-.*s on %s\n", NMAX, &p->ut_user[0], s); perror("open"); (void) fflush(stderr); _exit(1); } (void) fprintf(f, "\07\07\07Broadcast Message from %s (%s) on %s %19.19s", who, line, systm, time_buf); if (gflag) (void) fprintf(f, " to group %s", grpname); (void) fprintf(f, "...\n"); #ifdef DEBUG (void) fprintf(f, "DEBUG: To %.*s on %s\n", NMAX, p->ut_user, s); #endif i = strlen(mesg); for (bp = mesg; --i >= 0; bp++) { ibp = (unsigned int)((unsigned char) *bp); if (*bp == '\n') (void) putc('\r', f); if (isprint(ibp) || *bp == '\r' || *bp == '\013' || *bp == ' ' || *bp == '\t' || *bp == '\n' || *bp == '\007') { (void) putc(*bp, f); } else { if (!isascii(*bp)) { (void) fputs("M-", f); *bp = toascii(*bp); } if (iscntrl(*bp)) { (void) putc('^', f); (void) putc(*bp + 0100, f); } else (void) putc(*bp, f); } if (*bp == '\n') (void) fflush(f); if (ferror(f) || feof(f)) { (void) printf("\n\007Write failed\n"); (void) fflush(stdout); _exit(1); } } (void) fclose(f); (void) close(fd); _exit(0); }
int main(int ac, char *av[]) { char *dir = "/"; int allflag = 0; int df_allflag = 0; int opt_cnt = 0; int maxservers = 1024; /* zero allows inifinte number of threads */ int maxservers_set = 0; int logmaxservers = 0; int pid; int i; char *provider = (char *)NULL; char *df_provider = (char *)NULL; struct protob *protobp0, *protobp; NETSELDECL(proto) = NULL; NETSELDECL(df_proto) = NULL; NETSELPDECL(providerp); char *defval; boolean_t can_do_mlp; uint_t dss_npaths = 0; char **dss_pathnames = NULL; sigset_t sgset; char name[PATH_MAX], value[PATH_MAX]; int ret, bufsz; int pipe_fd = -1; MyName = *av; /* * Initializations that require more privileges than we need to run. */ (void) _create_daemon_lock(NFSD, DAEMON_UID, DAEMON_GID); svcsetprio(); can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP); if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS, can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) { (void) fprintf(stderr, "%s should be run with" " sufficient privileges\n", av[0]); exit(1); } /* Nfsd cannot run in a non-global zone. */ if (getzoneid() != GLOBAL_ZONEID) { (void) fprintf(stderr, "%s: can only run in the global zone\n", av[0]); exit(1); } (void) enable_extended_FILE_stdio(-1, -1); /* * Read in the values from SMF first before we check * command line options so the options override SMF values. */ bufsz = PATH_MAX; ret = nfs_smf_get_prop("max_connections", value, DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD, &bufsz); if (ret == SA_OK) { errno = 0; max_conns_allowed = strtol(value, (char **)NULL, 10); if (errno != 0) max_conns_allowed = -1; } bufsz = PATH_MAX; ret = nfs_smf_get_prop("listen_backlog", value, DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD, &bufsz); if (ret == SA_OK) { errno = 0; listen_backlog = strtol(value, (char **)NULL, 10); if (errno != 0) { listen_backlog = 32; } } bufsz = PATH_MAX; ret = nfs_smf_get_prop("protocol", value, DEFAULT_INSTANCE, SCF_TYPE_ASTRING, NFSD, &bufsz); if ((ret == SA_OK) && strlen(value) > 0) { df_proto = strdup(value); opt_cnt++; if (strncasecmp("ALL", value, 3) == 0) { free(df_proto); df_proto = NULL; df_allflag = 1; } } bufsz = PATH_MAX; ret = nfs_smf_get_prop("device", value, DEFAULT_INSTANCE, SCF_TYPE_ASTRING, NFSD, &bufsz); if ((ret == SA_OK) && strlen(value) > 0) { df_provider = strdup(value); opt_cnt++; } bufsz = PATH_MAX; ret = nfs_smf_get_prop("servers", value, DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD, &bufsz); if (ret == SA_OK) { errno = 0; maxservers = strtol(value, (char **)NULL, 10); if (errno != 0) maxservers = 1024; else maxservers_set = 1; } bufsz = 4; ret = nfs_smf_get_prop("server_versmin", value, DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD, &bufsz); if (ret == SA_OK) nfs_server_vers_min = strtol(value, (char **)NULL, 10); bufsz = 4; ret = nfs_smf_get_prop("server_versmax", value, DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD, &bufsz); if (ret == SA_OK) nfs_server_vers_max = strtol(value, (char **)NULL, 10); bufsz = PATH_MAX; ret = nfs_smf_get_prop("server_delegation", value, DEFAULT_INSTANCE, SCF_TYPE_ASTRING, NFSD, &bufsz); if (ret == SA_OK) if (strncasecmp(value, "off", 3) == 0) nfs_server_delegation = FALSE; /* * Conflict options error messages. */ if (opt_cnt > 1) { (void) fprintf(stderr, "\nConflicting options, only one of " "the following options can be specified\n" "in SMF:\n" "\tprotocol=ALL\n" "\tprotocol=protocol\n" "\tdevice=devicename\n\n"); usage(); } opt_cnt = 0; while ((i = getopt(ac, av, "ac:p:s:t:l:")) != EOF) { switch (i) { case 'a': free(df_proto); df_proto = NULL; free(df_provider); df_provider = NULL; allflag = 1; opt_cnt++; break; case 'c': max_conns_allowed = atoi(optarg); break; case 'p': proto = optarg; df_allflag = 0; opt_cnt++; break; /* * DSS: NFSv4 distributed stable storage. * * This is a Contracted Project Private interface, for * the sole use of Sun Cluster HA-NFS. See PSARC/2006/313. */ case 's': if (strlen(optarg) < MAXPATHLEN) { /* first "-s" option encountered? */ if (dss_pathnames == NULL) { /* * Allocate maximum possible space * required given cmdline arg count; * "-s <path>" consumes two args. */ size_t sz = (ac / 2) * sizeof (char *); dss_pathnames = (char **)malloc(sz); if (dss_pathnames == NULL) { (void) fprintf(stderr, "%s: " "dss paths malloc failed\n", av[0]); exit(1); } (void) memset(dss_pathnames, 0, sz); } dss_pathnames[dss_npaths] = optarg; dss_npaths++; } else { (void) fprintf(stderr, "%s: -s pathname too long.\n", av[0]); } break; case 't': provider = optarg; df_allflag = 0; opt_cnt++; break; case 'l': listen_backlog = atoi(optarg); break; case '?': usage(); /* NOTREACHED */ } } allflag = df_allflag; if (proto == NULL) proto = df_proto; if (provider == NULL) provider = df_provider; /* * Conflict options error messages. */ if (opt_cnt > 1) { (void) fprintf(stderr, "\nConflicting options, only one of " "the following options can be specified\n" "on the command line:\n" "\t-a\n" "\t-p protocol\n" "\t-t transport\n\n"); usage(); } if (proto != NULL && strncasecmp(proto, NC_UDP, strlen(NC_UDP)) == 0) { if (nfs_server_vers_max == NFS_V4) { if (nfs_server_vers_min == NFS_V4) { fprintf(stderr, "NFS version 4 is not supported " "with the UDP protocol. Exiting\n"); exit(3); } else { fprintf(stderr, "NFS version 4 is not supported " "with the UDP protocol.\n"); } } } /* * If there is exactly one more argument, it is the number of * servers. */ if (optind == ac - 1) { maxservers = atoi(av[optind]); maxservers_set = 1; } /* * If there are two or more arguments, then this is a usage error. */ else if (optind < ac - 1) usage(); /* * Check the ranges for min/max version specified */ else if ((nfs_server_vers_min > nfs_server_vers_max) || (nfs_server_vers_min < NFS_VERSMIN) || (nfs_server_vers_max > NFS_VERSMAX)) usage(); /* * There are no additional arguments, and we haven't set maxservers * explicitly via the config file, we use a default number of * servers. We will log this. */ else if (maxservers_set == 0) logmaxservers = 1; /* * Basic Sanity checks on options * * max_conns_allowed must be positive, except for the special * value of -1 which is used internally to mean unlimited, -1 isn't * documented but we allow it anyway. * * maxservers must be positive * listen_backlog must be positive or zero */ if (((max_conns_allowed != -1) && (max_conns_allowed <= 0)) || (listen_backlog < 0) || (maxservers <= 0)) { usage(); } /* * Set current dir to server root */ if (chdir(dir) < 0) { (void) fprintf(stderr, "%s: ", MyName); perror(dir); exit(1); } #ifndef DEBUG pipe_fd = daemonize_init(); #endif openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON); /* * establish our lock on the lock file and write our pid to it. * exit if some other process holds the lock, or if there's any * error in writing/locking the file. */ pid = _enter_daemon_lock(NFSD); switch (pid) { case 0: break; case -1: fprintf(stderr, "error locking for %s: %s\n", NFSD, strerror(errno)); exit(2); default: /* daemon was already running */ exit(0); } /* * If we've been given a list of paths to be used for distributed * stable storage, and provided we're going to run a version * that supports it, setup the DSS paths. */ if (dss_pathnames != NULL && nfs_server_vers_max >= DSS_VERSMIN) { if (dss_init(dss_npaths, dss_pathnames) != 0) { fprintf(stderr, "%s", "dss_init failed. Exiting.\n"); exit(1); } } /* * Block all signals till we spawn other * threads. */ (void) sigfillset(&sgset); (void) thr_sigsetmask(SIG_BLOCK, &sgset, NULL); if (logmaxservers) { fprintf(stderr, "Number of servers not specified. Using default of %d.\n", maxservers); } /* * Make sure to unregister any previous versions in case the * user is reconfiguring the server in interesting ways. */ svc_unreg(NFS_PROGRAM, NFS_VERSION); svc_unreg(NFS_PROGRAM, NFS_V3); svc_unreg(NFS_PROGRAM, NFS_V4); svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V2); svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V3); /* * Set up kernel RPC thread pool for the NFS server. */ if (nfssvcpool(maxservers)) { fprintf(stderr, "Can't set up kernel NFS service: %s. " "Exiting.\n", strerror(errno)); exit(1); } /* * Set up blocked thread to do LWP creation on behalf of the kernel. */ if (svcwait(NFS_SVCPOOL_ID)) { fprintf(stderr, "Can't set up NFS pool creator: %s. Exiting.\n", strerror(errno)); exit(1); } /* * RDMA start and stop thread. * Per pool RDMA listener creation and * destructor thread. * * start rdma services and block in the kernel. * (only if proto or provider is not set to TCP or UDP) */ if ((proto == NULL) && (provider == NULL)) { if (svcrdma(NFS_SVCPOOL_ID, nfs_server_vers_min, nfs_server_vers_max, nfs_server_delegation)) { fprintf(stderr, "Can't set up RDMA creator thread : %s\n", strerror(errno)); } } /* * Now open up for signal delivery */ (void) thr_sigsetmask(SIG_UNBLOCK, &sgset, NULL); sigset(SIGTERM, sigflush); sigset(SIGUSR1, quiesce); /* * Build a protocol block list for registration. */ protobp0 = protobp = (struct protob *)malloc(sizeof (struct protob)); protobp->serv = "NFS"; protobp->versmin = nfs_server_vers_min; protobp->versmax = nfs_server_vers_max; protobp->program = NFS_PROGRAM; protobp->next = (struct protob *)malloc(sizeof (struct protob)); protobp = protobp->next; protobp->serv = "NFS_ACL"; /* not used */ protobp->versmin = nfs_server_vers_min; /* XXX - this needs work to get the version just right */ protobp->versmax = (nfs_server_vers_max > NFS_ACL_V3) ? NFS_ACL_V3 : nfs_server_vers_max; protobp->program = NFS_ACL_PROGRAM; protobp->next = (struct protob *)NULL; if (allflag) { if (do_all(protobp0, nfssvc) == -1) { fprintf(stderr, "setnetconfig failed : %s\n", strerror(errno)); exit(1); } } else if (proto) { /* there's more than one match for the same protocol */ struct netconfig *nconf; NCONF_HANDLE *nc; bool_t protoFound = FALSE; if ((nc = setnetconfig()) == (NCONF_HANDLE *) NULL) { fprintf(stderr, "setnetconfig failed : %s\n", strerror(errno)); goto done; } while (nconf = getnetconfig(nc)) { if (strcmp(nconf->nc_proto, proto) == 0) { protoFound = TRUE; do_one(nconf->nc_device, NULL, protobp0, nfssvc); } } (void) endnetconfig(nc); if (protoFound == FALSE) { fprintf(stderr, "couldn't find netconfig entry for protocol %s\n", proto); } } else if (provider) do_one(provider, proto, protobp0, nfssvc); else { for (providerp = defaultproviders; *providerp != NULL; providerp++) { provider = *providerp; do_one(provider, NULL, protobp0, nfssvc); } } done: free(protobp); free(protobp0); if (num_fds == 0) { fprintf(stderr, "Could not start NFS service for any protocol." " Exiting.\n"); exit(1); } end_listen_fds = num_fds; /* * nfsd is up and running as far as we are concerned. */ daemonize_fini(pipe_fd); /* * Get rid of unneeded privileges. */ __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); /* * Poll for non-data control events on the transport descriptors. */ poll_for_action(); /* * If we get here, something failed in poll_for_action(). */ return (1); }
/*VARARGS1*/ int exec(int type, ...) { va_list args; int i; int procuid; int procgid; int ret; int fr_flg; char *cp; char *infile; char *outfile; char *errfile; char *sep; char **listp; char **file_list; char *printerName; char *printerNameToShow; static char nameBuf[100]; char *clean_title; PSTATUS *printer; RSTATUS *request; FSTATUS *form; EXEC *ep; PWSTATUS *pwheel; time_t now; struct passwd *pwp; #ifdef LP_USE_PAPI_ATTR struct stat tmpBuf; char tmpName[BUFSIZ]; char *path = NULL; #endif char *av[ARG_MAX]; char **envp = NULL; int ac = 0; char *mail_zonename = NULL; char *slabel = NULL; int setid = 1; char *ridno = NULL; syslog(LOG_DEBUG, "exec(%s)", _exec_name(type)); memset(av, 0, sizeof (*av)); va_start (args, type); switch (type) { case EX_INTERF: printer = va_arg(args, PSTATUS *); request = printer->request; ep = printer->exec; break; case EX_FAULT_MESSAGE: printer = va_arg(args, PSTATUS *); request = va_arg(args, RSTATUS *); if (! ( printer->status & (PS_FORM_FAULT | PS_SHOW_FAULT))) { return(0); } ep = printer->fault_exec; printerName = (printer->printer && printer->printer->name ? printer->printer->name : "??"); snprintf(nameBuf, sizeof (nameBuf), "%s (on %s)\n", printerName, Local_System); printerNameToShow = nameBuf; (void) time(&now); (void) strftime(time_buf, sizeof (time_buf), NULL, localtime(&now)); break; case EX_SLOWF: request = va_arg(args, RSTATUS *); ep = request->exec; break; case EX_NOTIFY: request = va_arg(args, RSTATUS *); if (request->request->actions & ACT_NOTIFY) { errno = EINVAL; return (-1); } ep = request->exec; break; case EX_ALERT: printer = va_arg(args, PSTATUS *); if (!(printer->printer->fault_alert.shcmd)) { errno = EINVAL; return(-1); } ep = printer->alert->exec; break; case EX_PALERT: pwheel = va_arg(args, PWSTATUS *); ep = pwheel->alert->exec; break; case EX_FORM_MESSAGE: (void) time(&now); (void) strftime(time_buf, sizeof (time_buf), NULL, localtime(&now)); /*FALLTHRU*/ case EX_FALERT: form = va_arg(args, FSTATUS *); ep = form->alert->exec; break; default: errno = EINVAL; return(-1); } va_end (args); if (!ep || (ep->pid > 0)) { errno = EBUSY; return(-1); } ep->flags = 0; key = ep->key = getkey(); switch ((ep->pid = Fork1(ep))) { case -1: relock (); return(-1); case 0: /* * We want to be able to tell our parent how we died. */ lp_alloc_fail_handler = child_mallocfail; break; default: switch(type) { case EX_INTERF: request->request->outcome |= RS_PRINTING; break; case EX_NOTIFY: request->request->outcome |= RS_NOTIFYING; break; case EX_SLOWF: request->request->outcome |= RS_FILTERING; request->request->outcome &= ~RS_REFILTER; break; } return(0); } for (i = 0; i < NSIG; i++) (void)signal (i, SIG_DFL); (void)signal (SIGALRM, SIG_IGN); (void)signal (SIGTERM, sigtrap); closelog(); for (i = 0; i < OpenMax; i++) if (i != ChildMd->writefd) Close (i); openlog("lpsched", LOG_PID|LOG_NDELAY|LOG_NOWAIT, LOG_LPR); setpgrp(); /* Set a default path */ addenv (&envp, "PATH", "/usr/lib/lp/bin:/usr/bin:/bin:/usr/sbin:/sbin"); /* copy locale related variables */ addenv (&envp, "TZ", getenv("TZ")); addenv (&envp, "LANG", getenv("LANG")); addenv (&envp, "LC_ALL", getenv("LC_ALL")); addenv (&envp, "LC_COLLATE", getenv("LC_COLLATE")); addenv (&envp, "LC_CTYPE", getenv("LC_CTYPE")); addenv (&envp, "LC_MESSAGES", getenv("LC_MESSAGES")); addenv (&envp, "LC_MONETARY", getenv("LC_MONETARY")); addenv (&envp, "LC_NUMERIC", getenv("LC_NUMERIC")); addenv (&envp, "LC_TIME", getenv("LC_TIME")); sprintf ((cp = BIGGEST_NUMBER_S), "%ld", key); addenv (&envp, "SPOOLER_KEY", cp); #if defined(DEBUG) addenv (&envp, "LPDEBUG", (debug? "1" : "0")); #endif /* * Open the standard input, standard output, and standard error. */ switch (type) { case EX_SLOWF: case EX_INTERF: /* * stdin: /dev/null * stdout: /dev/null (EX_SLOWF), printer port (EX_INTERF) * stderr: req# */ infile = 0; outfile = 0; errfile = makereqerr(request); break; case EX_NOTIFY: /* * stdin: req# * stdout: /dev/null * stderr: /dev/null */ infile = makereqerr(request); outfile = 0; errfile = 0; break; case EX_ALERT: case EX_FALERT: case EX_PALERT: case EX_FAULT_MESSAGE: case EX_FORM_MESSAGE: /* * stdin: /dev/null * stdout: /dev/null * stderr: /dev/null */ infile = 0; outfile = 0; errfile = 0; break; } if (infile) { if (Open(infile, O_RDONLY) == -1) Done (EXEC_EXIT_NOPEN, errno); } else { if (Open("/dev/null", O_RDONLY) == -1) Done (EXEC_EXIT_NOPEN, errno); } if (outfile) { if (Open(outfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1) Done (EXEC_EXIT_NOPEN, errno); } else { /* * If EX_INTERF, this is still needed to cause the * standard error channel to be #2. */ if (Open("/dev/null", O_WRONLY) == -1) Done (EXEC_EXIT_NOPEN, errno); } if (errfile) { if (Open(errfile, O_CREAT|O_TRUNC|O_WRONLY, 0600) == -1) Done (EXEC_EXIT_NOPEN, errno); } else { if (Open("/dev/null", O_WRONLY) == -1) Done (EXEC_EXIT_NOPEN, errno); } switch (type) { case EX_INTERF: /* * Opening a ``port'' can be dangerous to our health: * * - Hangups can occur if the line is dropped. * - The printer may send an interrupt. * - A FIFO may be closed, generating SIGPIPE. * * We catch these so we can complain nicely. */ trap_fault_signals (); (void)Close (1); if (strchr (request->request->user, '@')) { procuid = Lp_Uid; procgid = Lp_Gid; } else { procuid = request->secure->uid; procgid = request->secure->gid; } if (printer->printer->dial_info) { ret = open_dialup(request->printer_type, printer->printer); if (ret == 0) do_undial = 1; } else { ret = open_direct(request->printer_type, printer->printer); do_undial = 0; /* this is a URI */ if (is_printer_uri(printer->printer->device) == 0) addenv(&envp, "DEVICE_URI", printer->printer->device); } addenv(&envp, "DEVICE_URI", printer->printer->device); if (ret != 0) Done (ret, errno); if (!(request->request->outcome & RS_FILTERED)) file_list = request->request->file_list; else { register int count = 0; register char * num = BIGGEST_REQID_S; register char * prefix; prefix = makestr( Lp_Temp, "/F", getreqno(request->secure->req_id), "-", (char *)0 ); file_list = (char **)Malloc( (lenlist(request->request->file_list) + 1) * sizeof(char *) ); for ( listp = request->request->file_list; *listp; listp++ ) { sprintf (num, "%d", count + 1); file_list[count] = makestr( prefix, num, (char *)0 ); count++; } file_list[count] = 0; } #ifdef LP_USE_PAPI_ATTR /* * Check if the PAPI job attribute file exists, if it does * pass the file's pathname to the printer interface script * in an environment variable. This file is created when * print jobs are submitted via the PAPI interface. */ snprintf(tmpName, sizeof (tmpName), "%s-%s", getreqno(request->secure->req_id), LP_PAPIATTRNAME); path = makepath(Lp_Temp, tmpName, (char *)0); if ((path != NULL) && (stat(path, &tmpBuf) == 0)) { /* * IPP job attribute file exists for this job so * set the environment variable */ addenv(&envp, "ATTRPATH", path); } Free(path); /* * now set environment variable for the printer's PostScript * Printer Description (PPD) file, this is used by the filter * when forming the print data for this printer. */ if ((request->printer != NULL) && (request->printer->printer != NULL) && (request->printer->printer->name != NULL)) { snprintf(tmpName, sizeof (tmpName), "%s.ppd", request->printer->printer->name); path = makepath(ETCDIR, "ppd", tmpName, (char *)0); if ((path != NULL) && (stat(path, &tmpBuf) == 0)) { addenv(&envp, "PPD", path); } Free(path); } #endif if (request->printer_type) addenv(&envp, "TERM", request->printer_type); if (!(printer->printer->daisy)) { register char * chset = 0; register char * csp; if ( request->form && request->form->form->chset && request->form->form->mandatory && !STREQU(NAME_ANY, request->form->form->chset) ) chset = request->form->form->chset; else if ( request->request->charset && !STREQU(NAME_ANY, request->request->charset) ) chset = request->request->charset; if (chset) { csp = search_cslist( chset, printer->printer->char_sets ); /* * The "strtok()" below wrecks the string * for future use, but this is a child * process where it won't be needed again. */ addenv (&envp, "CHARSET", (csp? strtok(csp, "=") : chset) ); } } if (request->fast) addenv(&envp, "FILTER", request->fast); /* * Add the sensitivity label to the environment for * banner page and header/footer processing */ if (is_system_labeled() && request->secure->slabel != NULL) addenv(&envp, "SLABEL", request->secure->slabel); /* * Add the system name to the user name (ala system!user) * unless it is already there. RFS users may have trouble * here, sorry! */ cp = strchr(request->secure->user, '@'); allTraysWithForm(printer, request->form); /* * Fix for 4137389 * Remove double quotes from title string. */ fr_flg = 1; clean_title = strdup(NB(request->request->title)); if (clean_title == NULL) { /* * strdup failed. We're probably hosed * but try setting clean_title * to original title and continuing. */ clean_title = NB(request->request->title); fr_flg = 0; } else if (strcmp(clean_title, "") != 0) { char *ct_p; for (ct_p = clean_title; *ct_p != NULL; ct_p++) { if (*ct_p == '"') *ct_p = ' '; } } av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_A_Interfaces, printer->printer->name); /* * Read the options field of the request * In case of remote lpd request * the options field will have * job-id-requested. This is the * id sent by the client */ if (request->request->options != NULL) { char *options = NULL, *temp = NULL; options = temp = strdup(request->request->options); /* * Search for job-id-requested in * options string */ options = strstr(options, "job-id-requested"); if (options != NULL) { /* * Extract the ridno from the string * job-id-requested=xxx * In this case ridno = xxx */ if (STRNEQU(options, "job-id-requested=", 17)) { ridno = strdup(options + 17); if (ridno != NULL) /* * Read job-id-requested * successfully */ setid = 0; else /* * could not read * ridno from the string * job-id-requested=xxx */ setid = 1; } else /* * could not read * ridno from the string * job-id-requested=xxx */ setid = 1; } else /* * No job-id-requested in * request options */ setid = 1; if (temp != NULL) free(temp); } else /* * options field in request structure * not set */ setid = 1; /* * setid = 1 means the job-id-requested attribute * is not set so read the request->secure->req_id */ if (setid) av[ac++] = arg_string(TRUSTED, "%s", request->secure->req_id); else { /* * From request->secure->req_id extract the * printer-name. * request->secure->req_id = <printer-name>-<req_id> * The final req-id will be * <printer-name>-<ridno> */ char *r1 = NULL, *r2 = NULL, *tmp = NULL; r1 = r2 = tmp = strdup(request->secure->req_id); r2 = strrchr(r1, '-'); if (r2 != NULL) { char *r3 = NULL; int lr1 = strlen(r1); int lr2 = strlen(r2); r1[lr1 - lr2 + 1] = '\0'; /* * Now r1 = <printer-name>- */ lr1 = strlen(r1); lr2 = strlen(ridno); r3 = (char *)malloc(lr1+lr2+1); if (r3 != NULL) { strcpy(r3, r1); strcat(r3, ridno); /* * Here r3 = <printer-name>-<ridno> */ av[ac++] = arg_string(TRUSTED, "%s", r3); free(r3); } else av[ac++] = arg_string(TRUSTED, "%s", request->secure->req_id); } else av[ac++] = arg_string(TRUSTED, "%s", request->secure->req_id); if (tmp != NULL) free(tmp); if (ridno != NULL) free(ridno); } av[ac++] = arg_string(UNTRUSTED, "%s", request->request->user); av[ac++] = arg_string(TRUSTED, "%s", clean_title); av[ac++] = arg_string(TRUSTED, "%d", request->copies); if (fr_flg) free (clean_title); sep = ""; /* * Do the administrator defined key=value pair options */ argbuf[0] = '\0'; if (printer->printer->options) { char **tmp = printer->printer->options; while(*tmp != NULL) { STRLCAT(argbuf, sep, sizeof (argbuf)); sep = " "; STRLCAT(argbuf, *tmp++, sizeof (argbuf)); } } /* * Do the administrator defined ``stty'' stuff before * the user's -o options, to allow the user to override. */ if (printer->printer->stty) { STRLCAT (argbuf, sep, sizeof (argbuf)); sep = " "; STRLCAT (argbuf, "stty='", sizeof (argbuf)); STRLCAT (argbuf, printer->printer->stty, sizeof (argbuf)); STRLCAT (argbuf, "'", sizeof (argbuf)); } /* * Do all of the user's options except the cpi/lpi/etc. * stuff, which is done separately. */ if (request->request->options) { listp = dashos(request->request->options); while (*listp) { if ( !STRNEQU(*listp, "cpi=", 4) && !STRNEQU(*listp, "lpi=", 4) && !STRNEQU(*listp, "width=", 6) && !STRNEQU(*listp, "length=", 7) ) { STRLCAT (argbuf, sep, sizeof (argbuf)); sep = " "; STRLCAT (argbuf, *listp, sizeof (argbuf)); } listp++; } } /* * The "pickfilter()" routine (from "validate()") * stored the cpi/lpi/etc. stuff that should be * used for this request. It chose form over user, * and user over printer. */ if (request->cpi) { STRLCAT (argbuf, sep, sizeof (argbuf)); sep = " "; STRLCAT (argbuf, "cpi=", sizeof (argbuf)); STRLCAT (argbuf, request->cpi, sizeof (argbuf)); } if (request->lpi) { STRLCAT (argbuf, sep, sizeof (argbuf)); sep = " "; STRLCAT (argbuf, "lpi=", sizeof (argbuf)); STRLCAT (argbuf, request->lpi, sizeof (argbuf)); } if (request->pwid) { STRLCAT (argbuf, sep, sizeof (argbuf)); sep = " "; STRLCAT (argbuf, "width=", sizeof (argbuf)); STRLCAT (argbuf, request->pwid, sizeof (argbuf)); } if (request->plen) { STRLCAT (argbuf, sep, sizeof (argbuf)); sep = " "; STRLCAT (argbuf, "length=", sizeof (argbuf)); STRLCAT (argbuf, request->plen, sizeof (argbuf)); } /* * Do the ``raw'' bit last, to ensure it gets * done. If the user doesn't want this, then he or * she can do the correct thing using -o stty= * and leaving out the -r option. */ if (request->request->actions & ACT_RAW) { STRLCAT (argbuf, sep, sizeof (argbuf)); sep = " "; STRLCAT (argbuf, "stty=-opost", sizeof (argbuf)); } /* the "options" */ av[ac++] = arg_string(UNTRUSTED, "%s", argbuf); for (listp = file_list; *listp; listp++) av[ac++] = arg_string(TRUSTED, "%s", *listp); (void)chfiles (file_list, procuid, procgid); break; case EX_SLOWF: if (request->slow) addenv(&envp, "FILTER", request->slow); if (strchr (request->request->user, '@')) { procuid = Lp_Uid; procgid = Lp_Gid; } else { procuid = request->secure->uid; procgid = request->secure->gid; } cp = _alloc_files( lenlist(request->request->file_list), getreqno(request->secure->req_id), procuid, procgid); av[ac++] = arg_string(TRUSTED, "%s", Lp_Slow_Filter); av[ac++] = arg_string(TRUSTED, "%s/%s", Lp_Temp, cp); for (listp = request->request->file_list; *listp; listp++) av[ac++] = arg_string(TRUSTED, "%s", *listp); (void)chfiles (request->request->file_list, procuid, procgid); #ifdef LP_USE_PAPI_ATTR /* * Check if the PAPI job attribute file exists, if it does * pass the file's pathname to the slow-filters in an * environment variable. Note: this file is created when * print jobs are submitted via the PAPI interface. */ snprintf(tmpName, sizeof (tmpName), "%s-%s", getreqno(request->secure->req_id), LP_PAPIATTRNAME); path = makepath(Lp_Temp, tmpName, (char *)0); if ((path != NULL) && (stat(path, &tmpBuf) == 0)) { /* * IPP job attribute file exists for this job so * set the environment variable */ addenv(&envp, "ATTRPATH", path); } Free(path); /* * now set environment variable for the printer's PostScript * Printer Description (PPD) file, this is used by the filter * when forming the print data for this printer. */ if ((request->printer != NULL) && (request->printer->printer != NULL) && (request->printer->printer->name != NULL)) { snprintf(tmpName, sizeof (tmpName), "%s.ppd", request->printer->printer->name); path = makepath(ETCDIR, "ppd", tmpName, (char *)0); if ((path != NULL) && (stat(path, &tmpBuf) == 0)) { addenv(&envp, "PPD", path); } Free(path); } #endif break; case EX_ALERT: procuid = Lp_Uid; procgid = Lp_Gid; (void)Chown (printer->alert->msgfile, procuid, procgid); av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers, printer->printer->name, ALERTSHFILE); av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); break; case EX_PALERT: procuid = Lp_Uid; procgid = Lp_Gid; (void)Chown (pwheel->alert->msgfile, procuid, procgid); av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_PrintWheels, pwheel->pwheel->name, ALERTSHFILE); av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); break; case EX_FALERT: procuid = Lp_Uid; procgid = Lp_Gid; (void)Chown (form->alert->msgfile, procuid, procgid); av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms, form->form->name, ALERTSHFILE); av[ac++] = arg_string(TRUSTED, "%s", printer->alert->msgfile); break; case EX_FORM_MESSAGE: procuid = Lp_Uid; procgid = Lp_Gid; av[ac++] = arg_string(TRUSTED, "%s/form", Lp_A_Faults); av[ac++] = arg_string(TRUSTED, "%s", form->form->name); av[ac++] = arg_string(TRUSTED, "%s", time_buf); av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Forms, form->form->name, FORMMESSAGEFILE); break; case EX_FAULT_MESSAGE: procuid = Lp_Uid; procgid = Lp_Gid; av[ac++] = arg_string(TRUSTED, "%s/printer", Lp_A_Faults); av[ac++] = arg_string(TRUSTED, "%s", printerNameToShow); av[ac++] = arg_string(TRUSTED, "%s", time_buf); av[ac++] = arg_string(TRUSTED, "%s/%s/%s", Lp_A_Printers, printerName, FAULTMESSAGEFILE); break; case EX_NOTIFY: if (request->request->alert) { if (strchr(request->request->user, '@')) { procuid = Lp_Uid; procgid = Lp_Gid; } else { procuid = request->secure->uid; procgid = request->secure->gid; } av[ac++] = arg_string(TRUSTED, "%s", request->request->alert); } else { char *user = strdup(request->request->user); clean_string(user); slabel = request->secure->slabel; if (request->request->actions & ACT_WRITE) { av[ac++] = arg_string(TRUSTED, "%s", BINWRITE); snprintf(argbuf, sizeof (argbuf), "%s %s || %s %s", BINWRITE, user, BINMAIL, user ); av[ac++] = arg_string(TRUSTED, "/bin/sh"); av[ac++] = arg_string(TRUSTED, "-c"); av[ac++] = arg_string(TRUSTED, "%s", argbuf); } else if ((getzoneid() == GLOBAL_ZONEID) && is_system_labeled() && (slabel != NULL)) { /* * If in the global zone and the system is * labeled, mail is handled via a local * labeled zone that is the same label as * the request. */ if ((mail_zonename = get_labeled_zonename(slabel)) == (char *)-1) { /* * Cannot find labeled zone, just * return 0. */ return(0); } } if (mail_zonename == NULL) { procuid = Lp_Uid; procgid = Lp_Gid; av[ac++] = arg_string(TRUSTED, "%s", BINMAIL); av[ac++] = arg_string(UNTRUSTED, "%s", user); } else { procuid = getuid(); procgid = getgid(); av[ac++] = arg_string(TRUSTED, "%s", "/usr/sbin/zlogin"); av[ac++] = arg_string(TRUSTED, "%s", mail_zonename); av[ac++] = arg_string(TRUSTED, "%s", BINMAIL); av[ac++] = arg_string(UNTRUSTED, "%s", user); Free(mail_zonename); } free(user); } break; } av[ac++] = NULL; Fork2 (); /* only the child returns */ /* * Correctly set up the supplemental group list * for proper file access (before execl the interface program) */ pwp = getpwuid(procuid); if (pwp == NULL) { note("getpwuid(%d) call failed\n", procuid); } else if (initgroups(pwp->pw_name, procgid) < 0) { note("initgroups() call failed %d\n", errno); } setgid (procgid); setuid (procuid); /* * The shell doesn't allow the "trap" builtin to set a trap * for a signal ignored when the shell is started. Thus, don't * turn off signals in the last child! */ #ifdef DEBUG for (i = 0; av[i] != NULL; i++) note("exec(%s): av[%d] = %s", _exec_name(type), i, av[i]); for (i = 0; envp[i] != NULL; i++) note("exec(%s): envp[%d] = %s", _exec_name(type), i, envp[i]); #endif execvpe(av[0], av, envp); Done (EXEC_EXIT_NEXEC, errno); /*NOTREACHED*/ return (0); }