📄 btutils.c
字号:
/* Affix - Bluetooth Protocol Stack for Linux Copyright (C) 2001 Nokia Corporation Dmitry Kasatkin <dmitry.kasatkin@nokia.com> Based on the from Pontus Fuchs <pontus.fuchs@tactel.se> Copyright (c) 1999, 2000 Pontus Fuchs, All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* $Id: btutils.c,v 1.39 2003/02/18 13:39:11 kds Exp $ utility functions for Affix Fixes: Dmitry Kasatkin*/#include <affix/config.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/file.h>#include <signal.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <string.h>#include <dirent.h>#include <unistd.h>#include <errno.h>#include <time.h>/* pidof */#include <sys/wait.h>#include <dirent.h>#include <stdint.h>#include <affix/btcore.h>#include <affix/utils.h>/* Info about a process. */typedef struct _proc_{ char *fullname; /* Name as found out from argv[0] */ char *basename; /* Only the part after the last / */ char *statname; /* the statname without braces */ ino_t ino; /* Inode number */ dev_t dev; /* Device it is on */ pid_t pid; /* Process ID. */ int sid; /* Session ID. */ struct _proc_ *next; /* Pointer to next struct. */} PROC;/* pid queue */typedef struct _pidq_ { struct _pidq_ *front; struct _pidq_ *next; struct _pidq_ *rear; PROC *proc;} PIDQ;/* List of processes. */static PROC *plist = NULL;/* Did we stop a number of processes? */static int scripts_too = 0;//// Get some file-info. (size and lastmod)//int get_fileinfo(const char *name, char *lastmod){ struct stat stats; struct tm *tm; stat(name, &stats); tm = gmtime(&stats.st_mtime); snprintf(lastmod, 21, "%04d-%02d-%02dT%02d:%02d:%02dZ", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return (int) stats.st_size;}//// Read a file and alloc a buffer for it//uint8_t* easy_readfile(const char *filename, int *file_size){ int actual; int fd; uint8_t *buf; fd = open(filename, O_RDONLY, 0); if (fd == -1) { return NULL; } *file_size = get_filesize(filename); DBPRT("name=%s, size=%d\n", filename, *file_size); if(! (buf = malloc(*file_size)) ) { return NULL; } actual = read(fd, buf, *file_size); close(fd); *file_size = actual; return buf;}/* * Read the proc filesystem. */static int readproc(void){ DIR *dir; struct dirent *d; char path[256]; char buf[256]; char *s, *q; FILE *fp; int pid, f; PROC *p, *n; struct stat st; int c; /* Open the /proc directory. */ if ((dir = opendir("/proc")) == NULL) { BTERROR("cannot opendir(/proc)"); return -1; } /* Free the already existing process list. */ for (p = plist; p; p = n) { n = p->next; if (p->fullname) free(p->fullname); if (p->statname) free(p->statname); free(p); } plist = NULL; /* Walk through the directory. */ while ((d = readdir(dir)) != NULL) { /* See if this is a process */ if ((pid = atoi(d->d_name)) == 0) continue; /* Get a PROC struct . */ p = (PROC *)malloc(sizeof(PROC)); memset(p, 0, sizeof(PROC)); /* Open the status file. */ snprintf(path, sizeof(path), "/proc/%s/stat", d->d_name); /* Read SID & statname from it. */ if ((fp = fopen(path, "r")) != NULL) { buf[0] = 0; fgets(buf, 256, fp); /* See if name starts with '(' */ s = buf; while (*s != ' ') s++; s++; if (*s == '(') { /* Read program name. */ q = strrchr(buf, ')'); if (q == NULL) { p->sid = 0; BTERROR("can't get program name from %s\n", path); free(p); continue; } s++; } else { q = s; while (*q != ' ') q++; } *q++ = 0; while (*q == ' ') q++; p->statname = strdup(s); /* This could be replaced by getsid(pid) */ if (sscanf(q, "%*c %*d %*d %d", &p->sid) != 1) { p->sid = 0; BTERROR("can't read sid from %s\n", path); free(p); continue; } fclose(fp); } else { /* Process disappeared.. */ free(p); continue; } /* Now read argv[0] */ snprintf(path, sizeof(path), "/proc/%s/cmdline", d->d_name); if ((fp = fopen(path, "r")) != NULL) { f = 0; while(f < 127 && (c = fgetc(fp)) != EOF && c) buf[f++] = c; buf[f++] = 0; fclose(fp); /* Store the name into malloced memory. */ p->fullname = strdup(buf); /* Get a pointer to the basename. */ if ((p->basename = strrchr(p->fullname, '/')) != NULL) p->basename++; else p->basename = p->fullname; } else { /* Process disappeared.. */ free(p); continue; } /* Try to stat the executable. */ snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name); if (stat(path, &st) == 0) { p->dev = st.st_dev; p->ino = st.st_ino; } /* Link it into the list. */ p->next = plist; plist = p; p->pid = pid; } closedir(dir); /* Done. */ return 0;}static inline PIDQ *init_pid_q(PIDQ *q){ q->front = q->next = q->rear = NULL; q->proc = NULL; return q;}static inline int empty_q(PIDQ *q){ return (q->front == NULL);}static inline int add_pid_to_q(PIDQ *q, PROC *p){ PIDQ *tmp; tmp = (PIDQ *)malloc(sizeof(PIDQ)); tmp->proc = p; tmp->next = NULL; if (empty_q(q)) { q->front = tmp; q->rear = tmp; } else { q->rear->next = tmp; q->rear = tmp; } return 0;}static inline PROC *get_next_from_pid_q(PIDQ *q){ PROC *p; PIDQ *tmp = q->front; if (!empty_q(q)) { p = q->front->proc; q->front = tmp->next; free(tmp); return p; } return NULL;}/* Try to get the process ID of a given process. */static PIDQ *pidof(char *prog){ struct stat st; int dostat = 0; PROC *p; PIDQ *q; char *s; int foundone = 0; int ok = 0; /* Try to stat the executable. */ if (prog[0] == '/' && stat(prog, &st) == 0) dostat++; /* Get basename of program. */ if ((s = strrchr(prog, '/')) == NULL) s = prog; else s++; q = (PIDQ *)malloc(sizeof(PIDQ)); q = init_pid_q(q); /* First try to find a match based on dev/ino pair. */ if (dostat) { for (p = plist; p; p = p->next) { if (p->dev == st.st_dev && p->ino == st.st_ino) { add_pid_to_q(q, p); foundone++; } } } /* If we didn't find a match based on dev/ino, try the name. */ if (!foundone) { for (p = plist; p; p = p->next) { ok = 0; ok += (strcmp(p->fullname, prog) == 0); ok += (strcmp(p->basename, s) == 0); if (p->fullname[0] == 0 || strchr(p->fullname, ' ') || scripts_too) ok += (strcmp(p->statname, s) == 0); if (ok) add_pid_to_q(q, p); } } return q;}#define PIDOF_OMITSZ 5/* * Pidof functionality. */int affix_pidof(char *name, int flags, pid_t pid){ PROC *p; PIDQ *q; int i,oind; pid_t opid[PIDOF_OMITSZ], spid = 0; for (oind = PIDOF_OMITSZ-1; oind > 0; oind--) opid[oind] = 0; if (flags&PIDOF_SCRIPTS) scripts_too++; if (flags&PIDOF_OMIT) { opid[oind] = pid; oind++; } if (flags&PIDOF_POMIT) { opid[oind] = getppid(); oind++; } /* Print out process-ID's one by one. */ readproc(); if ((q = pidof(name)) != NULL) { spid = 0; while ((p = get_next_from_pid_q(q))) { if (flags & PIDOF_OMIT) { for (i = 0; i < oind; i++) if (opid[i] == p->pid) break; /* * On a match, continue with * the for loop above. */ if (i < oind) continue; } if (flags & PIDOF_SINGLE) { if (spid) continue; else spid = p->pid; } } } return spid;}#define isblank(c) (c == ' ' || c == '\t')char *xml_element(char **buf, char **attr){ char *start = *buf, *next; // find first < start = strchr(start, '<'); if (start == NULL) return NULL; start++; // find last > next = strchr(start, '>'); if (next == NULL) { // broken return NULL; } *next = '\0'; next++; *buf = next; // get first later of the element while (isblank(*start) && *start != '\0') start++; next = start+1; while (!isblank(*next) && *next != '\0') next++; *next = '\0'; *attr = next+1; // check for "/" next = *buf-1; while (*next == '\0' || isblank(*next)) next--; if (*next == '/') *next = '\0'; return start;}char *xml_attribute(char **buf, char **value){ char *start = *buf, *next; int flag = 0; //find attr name while (isblank(*start) && *start != '\0') start++; if (*start == '\0') return NULL; next = start+1; //find end while (!isblank(*next) && *next != '=' && *next != '\0') next++; if (*next == '=') flag = 1; *next = '\0'; next++; if (flag == 0) { next = strchr(next, '='); if (next == NULL) return NULL; next++; } next = strchr(next, '"'); if (next == NULL) return NULL; *value = next+1; next = strchr(next+1, '"'); if (next == NULL) return NULL; *next = '\0'; *buf = next+1; return start;}int rmkdir(char *new_dir, int mode){ size_t i = 0; DBPRT("new_dir: %s\n", new_dir); if (new_dir == NULL || new_dir[0] == '\0') return -1; if (access(new_dir, R_OK|X_OK) == 0) return 0; if (new_dir[0] == '/') i++; for (; new_dir[i] != '\0'; i++) { if (new_dir[i] == '/') { char tmpdir[PATH_MAX + 1]; strncpy (tmpdir, new_dir, i); tmpdir[i] = '\0'; if ((mkdir(tmpdir, mode) == -1) && (errno != EEXIST)) return -1; } } if (mkdir(new_dir, mode) == -1 && errno != EEXIST) return -1; return 0;}/* speed stuff */int get_speed(int size, struct timeval *tv_start, struct timeval *tv_end, long int *rsec, long int *rusec, double *speed){ long int sec, usec; sec = tv_end->tv_sec - tv_start->tv_sec; usec = (1000000 * sec) + tv_end->tv_usec - tv_start->tv_usec; *rsec = usec/1000000; *rusec = (usec - (*rsec * 1000000))/10000; *speed = (double)(size)/((double)(*rsec) + (double)(*rusec)/100); return 0;}/* Mapping */char *val2str(struct affix_tupla *map, int value){ for (;map; map++) { if (map->value == value) return map->str; } return "";}int str2val(struct affix_tupla *map, char *str, unsigned int *val){ char *fp, *tmp; struct affix_tupla *m; int found; if (!str || !(str = strdup(str))) return 0; *val = 0; found = 1; for (fp = strtok_r(str, ", ", &tmp); fp; fp = strtok_r(NULL, ", ", &tmp)) { //printf("arg: [%s]\n", fp); for (m = map; m->match || (found = 0); m++) { if (strcasecmp(fp, m->match) == 0) { *val = m->value; free(str); return 1; } } if (!found) { free(str); return 0; } } free(str); return 0;}int str2mask(struct affix_tupla *map, char *str, unsigned int *mask){ char *fp, *tmp; struct affix_tupla *m; int found; if (!str || !(str = strdup(str))) return 0; *mask = 0; found = 1; for (fp = strtok_r(str, ", ", &tmp); fp; fp = strtok_r(NULL, ", ", &tmp)) { //printf("arg: [%s]\n", fp); for (m = map; m->match || (found = 0); m++) { if (strcasecmp(fp, m->match) == 0) { *mask |= m->value; break; } } if (!found) { free(str); return 0; } } free(str); return 1;}int mask2str(struct affix_tupla *map, char *str, unsigned int mask){ int i = 0; struct affix_tupla *m; str[0] = '\0'; for (m = map; m->match; m++) { if (m->value & mask) i += sprintf(str + i, "%s ", m->match); } if (i) str[i-1] = '\0'; return 0;}int mask2str_comma(struct affix_tupla *map, char *str, unsigned int mask){ int i = 0; struct affix_tupla *m; str[0] = '\0'; for (m = map; m->match; m++) { if (m->value & mask) i += sprintf(str + i, "%s, ", m->match); } if (i) str[i-2] = '\0'; return 0;}int str2cod(char *str, uint32_t *cod){ struct affix_tupla *map; int found = 1; char *arg, *tmp; if (!str || !(str = strdup(str))) return -1; /* get Major */ arg = strtok_r(str, ", ", &tmp); if (arg == NULL) { free(str); return -1; } *cod = 0; for (map = codMajorClassMnemonic; map->match || (found=0); map++) { if (strncasecmp(map->match, arg, 3) == 0) { *cod |= map->value; break; } } if (!found){ free(str); return -1; } /* get minor */ arg = strtok_r(NULL, ", ", &tmp); if (arg == NULL) { free(str); return -1; } switch (*cod & HCI_COD_MAJOR) { case HCI_COD_COMPUTER: for (map = codMinorComputerMnemonic; map->match || (found=0); map++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -