📄 system.c
字号:
****************************************************************************/SMB_STRUCT_WPASSWD *wsys_getpwuid(uid_t uid){ static SMB_STRUCT_WPASSWD retval; struct passwd *pwret = sys_getpwuid(uid); if(!pwret) return NULL; unix_to_unicode(retval.pw_name, pwret->pw_name, sizeof(retval.pw_name)); retval.pw_passwd = pwret->pw_passwd; retval.pw_uid = pwret->pw_uid; retval.pw_gid = pwret->pw_gid; unix_to_unicode(retval.pw_gecos, pwret->pw_gecos, sizeof(retval.pw_gecos)); unix_to_unicode(retval.pw_dir, pwret->pw_dir, sizeof(retval.pw_dir)); unix_to_unicode(retval.pw_shell, pwret->pw_shell, sizeof(retval.pw_shell)); return &retval;}#endif /* NOT CURRENTLY USED - JRA *//************************************************************************** Extract a command into an arg list. Uses a static pstring for storage. Caller frees returned arg list (which contains pointers into the static pstring).****************************************************************************/static char **extract_args(const char *command){ static pstring trunc_cmd; char *ptr; int argcl; char **argl = NULL; int i; pstrcpy(trunc_cmd, command); if(!(ptr = strtok(trunc_cmd, " \t"))) { errno = EINVAL; return NULL; } /* * Count the args. */ for( argcl = 1; ptr; ptr = strtok(NULL, " \t")) argcl++; if((argl = (char **)SMB_MALLOC((argcl + 1) * sizeof(char *))) == NULL) return NULL; /* * Now do the extraction. */ pstrcpy(trunc_cmd, command); ptr = strtok(trunc_cmd, " \t"); i = 0; argl[i++] = ptr; while((ptr = strtok(NULL, " \t")) != NULL) argl[i++] = ptr; argl[i++] = NULL; return argl;}/************************************************************************** Wrapper for fork. Ensures that mypid is reset. Used so we can write a sys_getpid() that only does a system call *once*.****************************************************************************/static pid_t mypid = (pid_t)-1;pid_t sys_fork(void){ pid_t forkret = fork(); if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */ mypid = (pid_t) -1; return forkret;}/************************************************************************** Wrapper for getpid. Ensures we only do a system call *once*.****************************************************************************/pid_t sys_getpid(void){ if (mypid == (pid_t)-1) mypid = getpid(); return mypid;}/************************************************************************** Wrapper for popen. Safer as it doesn't search a path. Modified from the glibc sources. modified by tridge to return a file descriptor. We must kick our FILE* habit****************************************************************************/typedef struct _popen_list{ int fd; pid_t child_pid; struct _popen_list *next;} popen_list;static popen_list *popen_chain;int sys_popen(const char *command){ int parent_end, child_end; int pipe_fds[2]; popen_list *entry = NULL; char **argl = NULL; if (pipe(pipe_fds) < 0) return -1; parent_end = pipe_fds[0]; child_end = pipe_fds[1]; if (!*command) { errno = EINVAL; goto err_exit; } if((entry = SMB_MALLOC_P(popen_list)) == NULL) goto err_exit; ZERO_STRUCTP(entry); /* * Extract the command and args into a NULL terminated array. */ if(!(argl = extract_args(command))) goto err_exit; entry->child_pid = sys_fork(); if (entry->child_pid == -1) { goto err_exit; } if (entry->child_pid == 0) { /* * Child ! */ int child_std_end = STDOUT_FILENO; popen_list *p; close(parent_end); if (child_end != child_std_end) { dup2 (child_end, child_std_end); close (child_end); } /* * POSIX.2: "popen() shall ensure that any streams from previous * popen() calls that remain open in the parent process are closed * in the new child process." */ for (p = popen_chain; p; p = p->next) close(p->fd); execv(argl[0], argl); _exit (127); } /* * Parent. */ close (child_end); SAFE_FREE(argl); /* Link into popen_chain. */ entry->next = popen_chain; popen_chain = entry; entry->fd = parent_end; return entry->fd;err_exit: SAFE_FREE(entry); SAFE_FREE(argl); close(pipe_fds[0]); close(pipe_fds[1]); return -1;}/************************************************************************** Wrapper for pclose. Modified from the glibc sources.****************************************************************************/int sys_pclose(int fd){ int wstatus; popen_list **ptr = &popen_chain; popen_list *entry = NULL; pid_t wait_pid; int status = -1; /* Unlink from popen_chain. */ for ( ; *ptr != NULL; ptr = &(*ptr)->next) { if ((*ptr)->fd == fd) { entry = *ptr; *ptr = (*ptr)->next; status = 0; break; } } if (status < 0 || close(entry->fd) < 0) return -1; /* * As Samba is catching and eating child process * exits we don't really care about the child exit * code, a -1 with errno = ECHILD will do fine for us. */ do { wait_pid = sys_waitpid (entry->child_pid, &wstatus, 0); } while (wait_pid == -1 && errno == EINTR); SAFE_FREE(entry); if (wait_pid == -1) return -1; return wstatus;}/************************************************************************** Wrappers for dlopen, dlsym, dlclose.****************************************************************************/void *sys_dlopen(const char *name, int flags){#if defined(HAVE_DLOPEN) return dlopen(name, flags);#else return NULL;#endif}void *sys_dlsym(void *handle, const char *symbol){#if defined(HAVE_DLSYM) return dlsym(handle, symbol);#else return NULL;#endif}int sys_dlclose (void *handle){#if defined(HAVE_DLCLOSE) return dlclose(handle);#else return 0;#endif}const char *sys_dlerror(void){#if defined(HAVE_DLERROR) return dlerror();#else return NULL;#endif}int sys_dup2(int oldfd, int newfd) {#if defined(HAVE_DUP2) return dup2(oldfd, newfd);#else errno = ENOSYS; return -1;#endif}/************************************************************************** Wrapper for Admin Logs.****************************************************************************/ void sys_adminlog(int priority, const char *format_str, ...) { va_list ap; int ret; char *msgbuf = NULL; va_start( ap, format_str ); ret = vasprintf( &msgbuf, format_str, ap ); va_end( ap ); if (ret == -1) return;#if defined(HAVE_SYSLOG) syslog( priority, "%s", msgbuf );#else DEBUG(0,("%s", msgbuf ));#endif SAFE_FREE(msgbuf);}/************************************************************************** Wrappers for extented attribute calls. Based on the Linux package with support for IRIX and (Net|Free)BSD also. Expand as other systems have them.****************************************************************************/ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size){#if defined(HAVE_GETXATTR) return getxattr(path, name, value, size);#elif defined(HAVE_EXTATTR_GET_FILE) char *s; ssize_t retval; int attrnamespace = (strncmp(name, "system", 6) == 0) ? EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; /* * The BSD implementation has a nasty habit of silently truncating * the returned value to the size of the buffer, so we have to check * that the buffer is large enough to fit the returned value. */ if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) { if(retval > size) { errno = ERANGE; return -1; } if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0) return retval; } DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno))); return -1;#elif defined(HAVE_ATTR_GET) int retval, flags = 0; int valuelength = (int)size; char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; retval = attr_get(path, attrname, (char *)value, &valuelength, flags); return retval ? retval : valuelength;#else errno = ENOSYS; return -1;#endif}ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size){#if defined(HAVE_LGETXATTR) return lgetxattr(path, name, value, size);#elif defined(HAVE_EXTATTR_GET_LINK) char *s; ssize_t retval; int attrnamespace = (strncmp(name, "system", 6) == 0) ? EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) { if(retval > size) { errno = ERANGE; return -1; } if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0) return retval; } DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno))); return -1;#elif defined(HAVE_ATTR_GET) int retval, flags = ATTR_DONTFOLLOW; int valuelength = (int)size; char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; retval = attr_get(path, attrname, (char *)value, &valuelength, flags); return retval ? retval : valuelength;#else errno = ENOSYS; return -1;#endif}ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size){#if defined(HAVE_FGETXATTR) return fgetxattr(filedes, name, value, size);#elif defined(HAVE_EXTATTR_GET_FD) char *s; ssize_t retval; int attrnamespace = (strncmp(name, "system", 6) == 0) ? EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) { if(retval > size) { errno = ERANGE; return -1; } if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0) return retval; } DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno))); return -1;#elif defined(HAVE_ATTR_GETF) int retval, flags = 0; int valuelength = (int)size; char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags); return retval ? retval : valuelength;#else errno = ENOSYS; return -1;#endif}#if defined(HAVE_EXTATTR_LIST_FILE)#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)static struct { int space; const char *name; size_t len;} extattr[] = { { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") }, { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },};typedef union { const char *path; int filedes;} extattr_arg;static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size){ ssize_t list_size, total_size = 0; int i, t, len; char *buf; /* Iterate through extattr(2) namespaces */ for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) { switch(type) {#if defined(HAVE_EXTATTR_LIST_FILE) case 0: list_size = extattr_list_file(arg.path, extattr[t].space, list, size); break;#endif#if defined(HAVE_EXTATTR_LIST_LINK) case 1: list_size = extattr_list_link(arg.path, extattr[t].space, list, size); break;#endif#if defined(HAVE_EXTATTR_LIST_FD) case 2: list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size); break;#endif default: errno = ENOSYS; return -1; } /* Some error happend. Errno should be set by the previous call */ if(list_size < 0) return -1; /* No attributes */ if(list_size == 0) continue; /* XXX: Call with an empty buffer may be used to calculate necessary buffer size. Unfortunately, we can't say, how many attributes were returned, so here is the potential problem with the emulation. */ if(list == NULL) { /* Take the worse case of one char attribute names - two bytes per name plus one more for sanity. */ total_size += list_size + (list_size/2 + 1)*extattr[t].len; continue; } /* Count necessary offset to fit namespace prefixes */ len = 0; for(i = 0; i < list_size; i += list[i] + 1) len += extattr[t].len; total_size += list_size + len; /* Buffer is too small to fit the results */ if(total_size > size) { errno = ERANGE; return -1; } /* Shift results back, so we can prepend prefixes */ buf = memmove(list + len, list, list_size); for(i = 0; i < list_size; i += len + 1) { len = buf[i]; strncpy(list, extattr[t].name, extattr[t].len + 1); list += extattr[t].len; strncpy(list, buf + i + 1, len); list[len] = '\0'; list += len + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -