/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /*LINTLIBRARY*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include char * long_date() { static char longDate[64]; time_t curr; struct tm *tm; memset(longDate, 0, sizeof (longDate)); (void) time(&curr); if ((tm = localtime(&curr)) != NULL) (void) strftime(longDate, sizeof (longDate), "%b %d %R %Y", tm); return (longDate); } char * short_date() { static char shortDate[64]; time_t curr; struct tm *tm; memset(shortDate, 0, sizeof (shortDate)); (void) time(&curr); if ((tm = localtime(&curr)) != NULL) (void) strftime(shortDate, sizeof (shortDate), "%b %d %R", tm); return (shortDate); } /* * info about spool directory that we validate and fix */ #define ROOT_UID 0 #define LP_GID 8 #define SPOOL_MODE (S_IFDIR|S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) /*ARGSUSED*/ int check_client_spool(char *printer) { char *dir = SPOOL_DIR; struct stat st; if ((stat(dir, &st) < 0) && (errno == ENOENT)) { syslog(LOG_ERR, "no spool dir, creating %s", dir); if (mkdir(dir, 0755) < 0) { syslog(LOG_ERR, "mkdir(%s): %m", dir); return (-1); } if (chown(dir, ROOT_UID, LP_GID) < 0) { syslog(LOG_ERR, "chown(%s): %m", dir); return (-1); } return (0); } if ((st.st_uid != ROOT_UID) || (st.st_gid != LP_GID)) { syslog(LOG_ERR, "correcting spool directory owner/group (was %d/%d)", st.st_uid, st.st_gid); if (chown(dir, ROOT_UID, LP_GID) < 0) { syslog(LOG_ERR, "chown(%s): %m", dir); return (-1); } } if (st.st_mode != (S_IFDIR | SPOOL_MODE)) { syslog(LOG_ERR, "spool dir (%s), incorrect permission (%0), correcting", dir, st.st_mode); if (chmod(dir, 0755) < 0) { syslog(LOG_ERR, "chmod(%s): %m", dir); return (-1); } } return (0); } int get_lock(char *name, int write_pid) { int fd; syslog(LOG_DEBUG, "get_lock(%s, %d)", ((name != NULL) ? name : "NULL"), write_pid); if ((fd = open(name, O_RDWR|O_CREAT, 0640)) < 0) return (fd); if (lockf(fd, F_TLOCK, 0) < 0) { close(fd); return (-1); } if (write_pid != 0) { char pid[16]; if (ftruncate(fd, 0) < 0) { close(fd); return (-1); } if (snprintf(pid, sizeof (pid), "%d\n", (int)getpid()) >= sizeof (pid)) { syslog(LOG_ERR, "get_lock: pid buffer overflow"); return (-1); } write(fd, pid, strlen(pid)); } (void) fsync(fd); syslog(LOG_DEBUG, "get_lock(%s, %d) - have lock", ((name != NULL) ? name : "NULL"), write_pid); return (fd); } uid_t get_user_id(char *name) { struct passwd *p = NULL; if (name == NULL) return (-1); if ((p = getpwnam(name)) != NULL) return (p->pw_uid); else if ((p = getpwnam("nobody")) != NULL) return (p->pw_uid); else return (-2); } /* * get_user_name() */ char * get_user_name() { struct passwd *p = NULL; if ((p = getpwuid(getuid())) != NULL) return (strdup(p->pw_name)); else return (strdup("unknown")); } /* * strcdup() - duplicate a string up to the first occurence of a character */ char * strcdup(char *p, char c) { char *q, *r; if (p == NULL) return (NULL); if ((c == NULL) || ((q = strchr(p, c)) == NULL)) return (strdup(p)); if ((r = malloc((q - p) + 1)) != NULL) (void) strlcpy(r, p, ((q - p) + 1)); return (r); } /* * Should be obvious */ char * strndup(char *s, int l) { char *t; if ((s == NULL) || (l < 1)) return (NULL); if ((t = malloc(l + 1)) != NULL) (void) strlcpy(t, s, (l + 1)); return (t); } /* * file_size() - need I say more */ int file_size(char *path) { struct stat st; if (stat(path, &st) < 0) return (-1); else return (st.st_size); } /* * copy_file() - need I say more */ int copy_file(char *src, char *dst) { char *buf; int size; syslog(LOG_DEBUG, "copy_file(%s, %s)", ((src != NULL) ? src : "NULL"), ((dst != NULL) ? dst : "NULL")); if ((src == NULL) || (dst == NULL)) return (-1); if ((size = map_in_file(src, &buf, 1)) < 0) return (-1); if (write_buffer(dst, buf, size) < 0) { (void) munmap(buf, size); return (-1); } (void) munmap(buf, size); return (0); } int backup_file(char *name) { char buf[BUFSIZ]; if (snprintf(buf, sizeof (buf), "%s-", name) >= sizeof (buf)) { syslog(LOG_ERR, "libprint:backup_file: buffer overrun"); return (-1); } return (copy_file(name, buf)); } /* * map_in_file() - mmaps in a file into a buffer *buf. returns the size of * the mmapped buffer. */ int map_in_file(const char *file, char **buf, int as_me) { struct stat st; int fd; syslog(LOG_DEBUG, "map_in_file(%s)", (file ? file : "NULL")); if (buf == NULL) return (-1); if (as_me != 0) seteuid(getuid()); /* if we are suid, lose privilege */ if ((fd = open(file, O_RDONLY)) < 0) return (-1); if (as_me != 0) seteuid(0); /* if we fail, didn't have privilege before */ if (fstat(fd, &st) < 0) { close(fd); return (-1); } if (st.st_size == 0) { close(fd); *buf = NULL; return (0); } if ((*buf = mmap((caddr_t)0, (size_t)st.st_size, PROT_READ, (MAP_PRIVATE | MAP_NORESERVE), fd, (off_t)0)) == MAP_FAILED) { syslog(LOG_ERR, "map_in_file(%s) - mmap:%m", (file ? file : "NULL")); close(fd); return (-1); } close(fd); syslog(LOG_DEBUG, "map_in_file(%s) - size(%d), addr(0x%x)", (file ? file : "NULL"), st.st_size, *buf); return (st.st_size); } /* * write_buffer() - writes a buffer in memory out to the file name passed in. * uses mmap and ftruncate to do this. */ int write_buffer(char *file, char *buf, int len) { int fd; char *tmp; syslog(LOG_DEBUG, "write_buffer(%s, 0x%x, %d)", (file ? file : "NULL"), buf, len); if ((fd = open(file, O_CREAT|O_EXCL|O_RDWR, 0640)) < 0) return (-1); if (ftruncate(fd, len) < 0) { close(fd); return (-1); } if ((tmp = mmap((caddr_t)0, (size_t)len, PROT_READ| PROT_WRITE, (MAP_SHARED | MAP_NORESERVE), fd, (off_t)0)) == MAP_FAILED) { syslog(LOG_ERR, "write_buffer(%s, 0x%x, %d) - mmap:%m", (file ? file : "NULL"), buf, len); close(fd); return (-1); } close(fd); (void) memcpy(tmp, buf, len); (void) munmap(tmp, len); syslog(LOG_DEBUG, "write_buffer(%s, 0x%x, %d) - ok", (file ? file : "NULL"), buf, len); return (0); } /* * start_daemon() - check for jobs queued, check if the lock is free. If * so, start a daemon either by forking and execing or just execing * depending on the flag passed in. */ void start_daemon(int do_fork) { int lock; job_t **jobs = NULL; if ((jobs = job_list_append(NULL, NULL, NULL, SPOOL_DIR)) == NULL) return; list_iterate((void **)jobs, (VFUNC_T)job_free); free(jobs); close(lock = get_lock(MASTER_LOCK, 0)); if (lock < 0) return; if (do_fork == 0) { (void) execle("/usr/bin/lp", MASTER_NAME, NULL, NULL); syslog(LOG_ERR, "start_daemon() - execl: %m"); exit(-1); } else switch (fork()) { case -1: syslog(LOG_ERR, "start_daemon() - fork: %m"); exit(-1); /* NOTREACHED */ case 0: break; default: (void) execl("/usr/bin/lp", MASTER_NAME, NULL); syslog(LOG_ERR, "start_daemon() - execl: %m"); exit(-1); /* NOTREACHED */ } } /* * kill_daemon() - read the master lock file and send SIGTERM to the process * id stored in the file. */ int kill_process(char *file) { int fd, pid; char buf[BUFSIZ], *p; if ((fd = open(file, O_RDONLY)) < 0) return (-1); (void) memset(buf, NULL, sizeof (buf)); if (read(fd, buf, sizeof (buf)) <= 0) return (-1); if ((p = strchr(buf, '\n')) == NULL) { /* skip the 1st line */ close(fd); return (-1); } pid = atoi(++p); /* convert the PID */ if ((pid < 2) || (kill(pid, SIGTERM) < 0)) { close(fd); return (-1); } close(fd); return (0); } char ** strsplit(char *string, char *seperators) { char **list = NULL; char *where = NULL; char *element; for (element = strtok_r(string, seperators, &where); element != NULL; element = strtok_r(NULL, seperators, &where)) list = (char **)list_append((void **)list, element); return (list); }