diff options
Diffstat (limited to 'usr/src/lib/print/libprint/common/misc.c')
-rw-r--r-- | usr/src/lib/print/libprint/common/misc.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/usr/src/lib/print/libprint/common/misc.c b/usr/src/lib/print/libprint/common/misc.c new file mode 100644 index 0000000000..f9d7e4e966 --- /dev/null +++ b/usr/src/lib/print/libprint/common/misc.c @@ -0,0 +1,433 @@ +/* + * 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 <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <pwd.h> +#include <sys/mman.h> +#include <time.h> +#include <syslog.h> +#include <errno.h> + +#include <misc.h> +#include <job.h> +#include <list.h> + + +/* + * 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/lib/print/printd", 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/lib/print/printd", 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); +} |