⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sortformat.c

📁 linux下获取一些环境信息的代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright 1998-2004 by Albert Cahalan; all rights resered.          * This file may be used subject to the terms and conditions of the * GNU Library General Public License Version 2, or any later version   * at your option, as published by the Free Software Foundation. * 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 Library General Public License for more details. */                                 #include <stdlib.h>#include <stdio.h>#include <string.h>/* username lookups */#include <sys/types.h>#include <pwd.h>#include <grp.h>#include "../proc/readproc.h"#include "../proc/sysinfo.h"#include "common.h"static sf_node *sf_list = NULL;         /* deferred sorting and formatting */static int broken;                      /* use gross Unix98 parsing? */static int have_gnu_sort = 0;           /* if true, "O" must be format */static int already_parsed_sort = 0;     /* redundantly set in & out of fn */static int already_parsed_format = 0;/****************  Parse single format specifier *******************/static format_node *do_one_spec(const char *spec, const char *override){  const format_struct *fs;  const macro_struct *ms;  fs = search_format_array(spec);  if(fs){    int w1, w2;    format_node *thisnode;    thisnode = malloc(sizeof(format_node));    if(fs->flags & CF_PIDMAX){      w1 = (int)get_pid_digits();      w2 = strlen(fs->head);      if(w2>w1) w1=w2; // FIXME w/ separate header/body column sizing    }else{      w1 = fs->width;    }    if(override){      w2 = strlen(override);      thisnode->width = (w1>w2)?w1:w2;      thisnode->name = malloc(strlen(override)+1);      strcpy(thisnode->name, override);    }else{      thisnode->width = w1;      thisnode->name = malloc(strlen(fs->head)+1);      strcpy(thisnode->name, fs->head);    }    thisnode->pr = fs->pr;    thisnode->need = fs->need;    thisnode->vendor = fs->vendor;    thisnode->flags = fs->flags;    thisnode->next = NULL;    return thisnode;  }  /* That failed, so try it as a macro. */  ms = search_macro_array(spec);  if(ms){    format_node *list = NULL;    format_node *newnode;    const char *walk;    int dist;    char buf[16]; /* trust strings will be short (from above, not user) */    walk = ms->head;    while(*walk){      dist = strcspn(walk, ", ");      strncpy(buf,walk,dist);      buf[dist] = '\0';      newnode = do_one_spec(buf,override); /* call self, assume success */      newnode->next = list;      list = newnode;      walk += dist;      if(*walk) walk++;    }    return list;  }  return NULL;   /* bad, spec not found */}/************ must wrap user format in default *************/static void O_wrap(sf_node *sfn, int otype){  format_node *fnode;  format_node *endp;  const char *trailer;  trailer = (otype=='b') ? "END_BSD" : "END_SYS5" ;  fnode =  do_one_spec("pid",NULL);  if(!fnode)fprintf(stderr,"Seriously crashing. Goodbye cruel world.\n");  endp = sfn->f_cooked; while(endp->next) endp = endp->next;  /* find end */  endp->next = fnode;    fnode =  do_one_spec(trailer,NULL);  if(!fnode)fprintf(stderr,"Seriously crashing. Goodbye cruel world.\n");  endp = fnode; while(endp->next) endp = endp->next;  /* find end */  endp->next = sfn->f_cooked;  sfn->f_cooked = fnode;}/****************************************************************** * Used to parse option AIX field descriptors. * Put each completed format_node onto the list starting at ->f_cooked */static const char *aix_format_parse(sf_node *sfn){  char *buf;                   /* temp copy of arg to hack on */  char *walk;  int items;  /*** sanity check and count items ***/  items = 0;  walk = sfn->sf;  /* state machine */ {  int c;  initial:    c = *walk++;    if(c=='%')    goto get_desc;    if(!c)        goto looks_ok;  /* get_text: */    items++;  get_more_text:    c = *walk++;    if(c=='%')    goto get_desc;    if(c)         goto get_more_text;    goto looks_ok;  get_desc:    items++;    c = *walk++;    if(c)         goto initial;    return "Improper AIX field descriptor.";  looks_ok:    ;  }  /*** sanity check passed ***/  buf = malloc(strlen(sfn->sf)+1);  strcpy(buf, sfn->sf);  walk = sfn->sf;    while(items--){    format_node *fnode;  /* newly allocated */    format_node *endp;   /* for list manipulation */    if(*walk == '%'){      const aix_struct *aix;      walk++;      if(*walk == '%') goto double_percent;      aix = search_aix_array(*walk);      walk++;      if(!aix){        free(buf);        return "Unknown AIX field descriptor.";      }      fnode =  do_one_spec(aix->spec, aix->head);      if(!fnode){        free(buf);        return "AIX field descriptor processing bug.";      }    } else {      int len;      len = strcspn(walk, "%");      memcpy(buf,walk,len);      if(0){double_percent:        len = 1;        buf[0] = '%';      }      buf[len] = '\0';      walk += len;      fnode = malloc(sizeof(format_node));      fnode->width = len;      fnode->name = malloc(len+1);      strcpy(fnode->name, buf);      fnode->pr = NULL;     /* checked for */      fnode->need = 0;      fnode->vendor = AIX;      fnode->flags = CF_PRINT_EVERY_TIME;      fnode->next = NULL;    }        endp = fnode; while(endp->next) endp = endp->next;  /* find end */    endp->next = sfn->f_cooked;    sfn->f_cooked = fnode;  }  free(buf);  already_parsed_format = 1;  return NULL;}/*************************************************************** * Used to parse option O lists. Option O is shared between * sorting and formatting. Users may expect one or the other. * The "broken" flag enables a really bad Unix98 misfeature. * Put each completed format_node onto the list starting at ->f_cooked */static const char *format_parse(sf_node *sfn){  char *buf;                   /* temp copy of arg to hack on */  char *sep_loc;               /* separator location: " \t,\n" */  char *walk;  const char *err;       /* error code that could or did happen */  format_node *fnode;  int items;  int need_item;  static char errbuf[80]; /* for variable-text error message */  /*** prepare to operate ***/  buf = malloc(strlen(sfn->sf)+1);  strcpy(buf, sfn->sf);    /*** sanity check and count items ***/  need_item = 1; /* true */  items = 0;  walk = buf;  do{    switch(*walk){    case ' ': case ',': case '\t': case '\n': case '\0':    /* Linux extension: allow \t and \n as delimiters */      if(need_item){        free(buf);        goto improper;      }      need_item=1;      break;    case '=':      if(broken) goto out;      /* fall through */    default:      if(need_item) items++;      need_item=0;    }  } while (*++walk);out:  if(!items){    free(buf);    goto empty;  }#ifdef STRICT_LIST  if(need_item){    /* can't have trailing deliminator */    free(buf);    goto improper;  }#else  if(need_item){    /* allow 1 trailing deliminator */    *--walk='\0';  /* remove the trailing deliminator */  }#endif  /*** actually parse the list ***/  walk = buf;  while(items--){    format_node *endp;    char *equal_loc;    char *colon_loc;    sep_loc = strpbrk(walk," ,\t\n");    /* if items left, then sep_loc is not in header override */    if(items && sep_loc) *sep_loc = '\0';    equal_loc = strpbrk(walk,"=");    if(equal_loc){   /* if header override */      *equal_loc = '\0';      equal_loc++;    }    colon_loc = strpbrk(walk,":");    if(colon_loc){   /* if width override */      *colon_loc = '\0';      colon_loc++;      if(strspn(colon_loc,"0123456789") != strlen(colon_loc) || *colon_loc=='0' || !*colon_loc){        free(buf);        goto badwidth;      }    }    fnode =  do_one_spec(walk,equal_loc);    if(!fnode){      if(!*errbuf){  /* if didn't already create an error string */        snprintf(          errbuf,          sizeof(errbuf),          "Unknown user-defined format specifier \"%s\".",          walk        );      }      free(buf);      goto unknown;    }    if(colon_loc){      if(fnode->next){        free(buf);        goto notmacro;      }      // FIXME: enforce signal width to 8, 9, or 16 (grep: SIGNAL wide_signals)      fnode->width = atoi(colon_loc); // already verified to be a number    }    endp = fnode; while(endp->next) endp = endp->next;  /* find end */    endp->next = sfn->f_cooked;    sfn->f_cooked = fnode;    walk = sep_loc + 1; /* point to next item, if any */  }  free(buf);  already_parsed_format = 1;  return NULL;  /* errors may cause a retry looking for AIX format codes */  if(0) unknown:  err=errbuf;  if(0) empty:    err="Empty format list.";  if(0) improper: err="Improper format list.";  if(0) badwidth: err="Column widths must be unsigned decimal numbers.";  if(0) notmacro: err="Can't set width for a macro (multi-column) format specifier.";  if(strchr(sfn->sf,'%')) err = aix_format_parse(sfn);  return err;}/****************  Parse single sort specifier *******************/static sort_node *do_one_sort_spec(const char *spec){  const format_struct *fs;  int reverse = 0;  if(*spec == '-'){    reverse = 1;    spec++;  }  fs = search_format_array(spec);  if(fs){    sort_node *thisnode;    thisnode = malloc(sizeof(sort_node));    thisnode->sr = fs->sr;    thisnode->need = fs->need;    thisnode->reverse = reverse;    thisnode->next = NULL;    return thisnode;  }  return NULL;   /* bad, spec not found */}/************************************************************** * Used to parse long sorting options. * Put each completed sort_node onto the list starting at ->s_cooked */static const char *long_sort_parse(sf_node *sfn){  char *buf;                   /* temp copy of arg to hack on */  char *sep_loc;               /* separator location: " \t,\n" */  char *walk;  sort_node *snode;  int items;  int need_item;  /*** prepare to operate ***/  buf = malloc(strlen(sfn->sf)+1);  strcpy(buf, sfn->sf);    /*** sanity check and count items ***/  need_item = 1; /* true */  items = 0;  walk = buf;  do{    switch(*walk){    case ' ': case ',': case '\t': case '\n': case '\0':      if(need_item){        free(buf);        return "Improper sort list";      }      need_item=1;      break;    default:      if(need_item) items++;      need_item=0;    }  } while (*++walk);  if(!items){    free(buf);    return "Empty sort list.";  }#ifdef STRICT_LIST  if(need_item){    /* can't have trailing deliminator */    free(buf);    return "Improper sort list.";  }#else  if(need_item){    /* allow 1 trailing deliminator */    *--walk='\0';  /* remove the trailing deliminator */  }#endif  /*** actually parse the list ***/  walk = buf;  while(items--){    sort_node *endp;    sep_loc = strpbrk(walk," ,\t\n");    if(sep_loc) *sep_loc = '\0';    snode = do_one_sort_spec(walk);    if(!snode){      free(buf);      return "Unknown sort specifier.";    }    endp = snode; while(endp->next) endp = endp->next;  /* find end */    endp->next = sfn->s_cooked;    sfn->s_cooked = snode;    walk = sep_loc + 1; /* point to next item, if any */  }  free(buf);  already_parsed_sort = 1;  return NULL;}/************ pre-parse short sorting option *************//* Errors _must_ be detected so that the "O" option can try to * reparse as formatting codes. */static const char *verify_short_sort(const char *arg){  const char all[] = "CGJKMNPRSTUcfgjkmnoprstuvy+-";  char checkoff[256];  int i;  const char *walk;  int tmp;  if(strspn(arg,all) != strlen(arg)) return "Bad sorting code.";  for(i=256; i--;) checkoff[i] = 0;  walk = arg;  for(;;){    tmp = *walk;    switch(tmp){    case '\0':      return NULL;   /* looks good */    case '+':    case '-':      tmp = *(walk+1);      if(!tmp || tmp=='+' || tmp=='-') return "Bad sorting code.";      break;    case 'P':      if(forest_type) return "PPID sort and forest output conflict.";      /* fall through */    default:      if(checkoff[tmp]) return "Bad sorting code.";   /* repeated */      /* ought to check against already accepted sort options */      checkoff[tmp] = 1;      break;    }    walk++;  }}/************ parse short sorting option *************/static const char *short_sort_parse(sf_node *sfn){  int direction = 0;  const char *walk;  int tmp;  sort_node *snode;  sort_node *endp;  const struct shortsort_struct *ss;  walk = sfn->sf;  for(;;){    tmp = *walk;    switch(tmp){    case '\0':      already_parsed_sort = 1;      return NULL;    case '+':      direction = 0;      break;    case '-':      direction = 1;      break;    default:      ss = search_shortsort_array(tmp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -