?? parser.c
字號:
sizeof(gnu_table_struct), compare_gnu_table_structs ); if(!found) return "Unknown gnu long option."; goto *(found->jump); /* See gcc extension info. :-) */ case_Group: trace("--Group\n"); arg = grab_gnu_arg(); if(!arg) return "List of real groups must follow --Group."; err=parse_list(arg, parse_gid); if(err) return err; selection_list->typecode = SEL_RGID; return NULL; case_User: trace("--User\n"); arg = grab_gnu_arg(); if(!arg) return "List of real users must follow --User."; err=parse_list(arg, parse_uid); if(err) return err; selection_list->typecode = SEL_RUID; return NULL; case_cols: case_width: case_columns: trace("--cols\n"); arg = grab_gnu_arg(); if(arg && *arg){ long t; char *endptr; t = strtol(arg, &endptr, 0); if(!*endptr && (t>0) && (t<2000000000)){ screen_cols = (int)t; return NULL; } } return "Number of columns must follow --cols, --width, or --columns."; case_cumulative: trace("--cumulative\n"); if(s[sl]) return "Option --cumulative does not take an argument."; include_dead_children = 1; return NULL; case_deselect: trace("--deselect\n"); if(s[sl]) return "Option --deselect does not take an argument."; negate_selection = 1; return NULL; case_no_header: case_no_headers: case_no_heading: case_no_headings: case_noheader: case_noheaders: case_noheading: case_noheadings: trace("--noheaders\n"); if(s[sl]) return "Option --no-heading does not take an argument."; if(header_type) return "Only one heading option may be specified."; header_type = HEAD_NONE; return NULL; case_header: case_headers: case_heading: case_headings: trace("--headers\n"); if(s[sl]) return "Option --heading does not take an argument."; if(header_type) return "Only one heading option may be specified."; header_type = HEAD_MULTI; return NULL; case_forest: trace("--forest\n"); if(s[sl]) return "Option --forest does not take an argument."; forest_type = 'g'; return NULL; case_format: trace("--format\n"); arg=grab_gnu_arg(); if(!arg) return "Format specification must follow --format."; defer_sf_option(arg, SF_G_format); return NULL; case_group: trace("--group\n"); arg = grab_gnu_arg(); if(!arg) return "List of effective groups must follow --group."; err=parse_list(arg, parse_gid); if(err) return err; selection_list->typecode = SEL_EGID; return NULL; case_help: trace("--help\n"); exclusive("--help"); fwrite(help_message,1,strlen(help_message),stdout); exit(0); return NULL; case_info: trace("--info\n"); exclusive("--info"); self_info(); exit(0); return NULL; case_pid: trace("--pid\n"); arg = grab_gnu_arg(); if(!arg) return "List of process IDs must follow --pid."; err=parse_list(arg, parse_pid); if(err) return err; selection_list->typecode = SEL_PID; return NULL; case_ppid: trace("--ppid\n"); arg = grab_gnu_arg(); if(!arg) return "List of process IDs must follow --ppid."; err=parse_list(arg, parse_pid); if(err) return err; selection_list->typecode = SEL_PPID; return NULL; case_rows: case_lines: trace("--rows\n"); arg = grab_gnu_arg(); if(arg && *arg){ long t; char *endptr; t = strtol(arg, &endptr, 0); if(!*endptr && (t>0) && (t<2000000000)){ screen_rows = (int)t; return NULL; } } return "Number of rows must follow --rows or --lines."; case_sid: trace("--sid\n"); arg = grab_gnu_arg(); if(!arg) return "Some sid thing(s) must follow --sid."; err=parse_list(arg, parse_pid); if(err) return err; selection_list->typecode = SEL_SESS; return NULL; case_sort: trace("--sort\n"); arg=grab_gnu_arg(); if(!arg) return "Long sort specification must follow --sort."; defer_sf_option(arg, SF_G_sort); return NULL; case_tty: trace("--tty\n"); arg = grab_gnu_arg(); if(!arg) return "List of ttys must follow --tty."; err=parse_list(arg, parse_tty); if(err) return err; selection_list->typecode = SEL_TTY; return NULL; case_user: trace("--user\n"); arg = grab_gnu_arg(); if(!arg) return "List of effective users must follow --user."; err=parse_list(arg, parse_uid); if(err) return err; selection_list->typecode = SEL_EUID; return NULL; case_version: trace("--version\n"); exclusive("--version"); display_version(); exit(0); return NULL; case_context: trace("--context\n"); format_flags |= FF_Fc; return NULL;}/*************** process trailing PIDs **********************/static const char *parse_trailing_pids(void){ selection_node *pidnode; /* pid */ selection_node *grpnode; /* process group */ selection_node *sidnode; /* session */ char **argp; /* pointer to pointer to text of PID */ const char *err; /* error code that could or did happen */ int i; i = ps_argc - thisarg; /* how many trailing PIDs, SIDs, PGRPs?? */ argp = ps_argv + thisarg; thisarg = ps_argc - 1; /* we must be at the end now */ pidnode = malloc(sizeof(selection_node)); pidnode->u = malloc(i*sizeof(sel_union)); /* waste is insignificant */ pidnode->n = 0; grpnode = malloc(sizeof(selection_node)); grpnode->u = malloc(i*sizeof(sel_union)); /* waste is insignificant */ grpnode->n = 0; sidnode = malloc(sizeof(selection_node)); sidnode->u = malloc(i*sizeof(sel_union)); /* waste is insignificant */ sidnode->n = 0; while(i--){ char *data; data = *(argp++); switch(*data){ default: err = parse_pid( data, pidnode->u + pidnode->n++); break; case '-': err = parse_pid(++data, grpnode->u + grpnode->n++); break; case '+': err = parse_pid(++data, sidnode->u + sidnode->n++); break; } if(err) return err; /* the node gets freed with the list */ } if(pidnode->n){ pidnode->next = selection_list; selection_list = pidnode; selection_list->typecode = SEL_PID; } /* else free both parts */ if(grpnode->n){ grpnode->next = selection_list; selection_list = grpnode; selection_list->typecode = SEL_PGRP; } /* else free both parts */ if(sidnode->n){ sidnode->next = selection_list; selection_list = sidnode; selection_list->typecode = SEL_SESS; } /* else free both parts */ return NULL;}/************** misc stuff ***********/static void reset_parser(void){ w_count = 0;}static int arg_type(const char *str){ int tmp = str[0]; if((tmp>='a') && (tmp<='z')) return ARG_BSD; if((tmp>='A') && (tmp<='Z')) return ARG_BSD; if((tmp>='0') && (tmp<='9')) return ARG_PID; if(tmp=='+') return ARG_SESS; if(tmp!='-') return ARG_FAIL; tmp = str[1]; if((tmp>='a') && (tmp<='z')) return ARG_SYSV; if((tmp>='A') && (tmp<='Z')) return ARG_SYSV; if((tmp>='0') && (tmp<='9')) return ARG_PGRP; if(tmp!='-') return ARG_FAIL; tmp = str[2]; if((tmp>='a') && (tmp<='z')) return ARG_GNU; if((tmp>='A') && (tmp<='Z')) return ARG_GNU; if(tmp=='\0') return ARG_END; return ARG_FAIL;}/* First assume sysv, because that is the POSIX and Unix98 standard. */static const char *parse_all_options(void){ const char *err = NULL; int at; while(++thisarg < ps_argc){ trace("parse_all_options calling arg_type for \"%s\"\n", ps_argv[thisarg]); at = arg_type(ps_argv[thisarg]); trace("ps_argv[thisarg] is %s\n", ps_argv[thisarg]); if(at != ARG_SYSV) not_pure_unix = 1; switch(at){ case ARG_GNU: err = parse_gnu_option(); break; case ARG_SYSV: if(!force_bsd){ /* else go past case ARG_BSD */ err = parse_sysv_option(); break; case ARG_BSD: if(force_bsd && !(personality & PER_FORCE_BSD)) return "way bad"; } prefer_bsd_defaults = 1; err = parse_bsd_option(); break; case ARG_PGRP: case ARG_SESS: case ARG_PID: prefer_bsd_defaults = 1; err = parse_trailing_pids(); break; case ARG_END: case ARG_FAIL: trace(" FAIL/END on [%s]\n",ps_argv[thisarg]); return "Garbage option."; break; default: printf(" ? %s\n",ps_argv[thisarg]); return "Something broke."; } /* switch */ if(err) return err; } /* while */ return NULL;}static void choose_dimensions(void){ if(w_count && (screen_cols<132)) screen_cols=132; if(w_count>1) screen_cols=OUTBUF_SIZE; /* perhaps --html and --null should set unlimited width */}static const char *thread_option_check(void){ if(!thread_flags){ thread_flags = TF_show_proc; return NULL; } if(forest_type){ return "Thread display conflicts with forest display."; } //thread_flags |= TF_no_forest; if((thread_flags&TF_B_H) && (thread_flags&(TF_B_m|TF_U_m))) return "Thread flags conflict; can't use H with m or -m."; if((thread_flags&TF_B_m) && (thread_flags&TF_U_m)) return "Thread flags conflict; can't use both m and -m."; if((thread_flags&TF_U_L) && (thread_flags&TF_U_T)) return "Thread flags conflict; can't use both -L and -T."; if(thread_flags&TF_B_H) thread_flags |= (TF_show_proc|TF_loose_tasks); if(thread_flags&(TF_B_m|TF_U_m)) thread_flags |= (TF_show_proc|TF_show_task|TF_show_both); if(thread_flags&(TF_U_T|TF_U_L)){ if(thread_flags&(TF_B_m|TF_U_m|TF_B_H)){ // Got a thread style, so format modification is a requirement? // Maybe -T/-L has H thread style though. (sorting interaction?) //return "Huh? Tell procps-feedback@lists.sf.net what you expected."; thread_flags |= TF_must_use; }else{ // using -L/-T thread style, so format from elsewhere is OK thread_flags |= TF_show_task; // or like the H option? //thread_flags |= TF_no_sort; } } return NULL;}int arg_parse(int argc, char *argv[]){ const char *err = NULL; const char *err2 = NULL; ps_argc = argc; ps_argv = argv; thisarg = 0; if(personality & PER_FORCE_BSD) goto try_bsd; err = parse_all_options(); if(err) goto try_bsd; err = thread_option_check(); if(err) goto try_bsd; err = process_sf_options(!not_pure_unix); if(err) goto try_bsd; err = select_bits_setup(); if(err) goto try_bsd; choose_dimensions(); return 0;try_bsd: trace("--------- now try BSD ------\n"); reset_global(); reset_parser(); reset_sortformat(); format_flags = 0; ps_argc = argc; ps_argv = argv; thisarg = 0; /* no need to reset flagptr */ not_pure_unix=1; force_bsd=1; prefer_bsd_defaults=1; if(!( (PER_OLD_m|PER_BSD_m) & personality )) /* if default m setting... */ personality |= PER_OLD_m; /* Prefer old Linux over true BSD. */ /* Do not set PER_FORCE_BSD! It is tested below. */ err2 = parse_all_options(); if(err2) goto total_failure; err2 = thread_option_check(); if(err2) goto total_failure; err2 = process_sf_options(!not_pure_unix); if(err2) goto total_failure; err2 = select_bits_setup(); if(err2) goto total_failure; // Feel a need to patch this out? First of all, read the FAQ. // Second of all, talk to me. Without this warning, people can // get seriously confused. Ask yourself if users would freak out // about "ps -aux" suddenly changing behavior if a user "x" were // added to the system. // // Also, a "-x" option is coming. It's already there in fact, // for some non-default personalities. So "ps -ax" will parse // as SysV options... and you're screwed if you've been patching // out the friendly warning. Cut-over is likely to be in 2005. if(!(personality & PER_FORCE_BSD)) fprintf(stderr, "Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html\n"); // Remember: contact albert@users.sf.net or procps-feedback@lists.sf.net // if you should feel tempted. Be damn sure you understand all // the issues. The same goes for other stuff too, BTW. Please ask. // I'm happy to justify various implementation choices. choose_dimensions(); return 0;total_failure: reset_parser(); if(personality & PER_FORCE_BSD) fprintf(stderr, "ERROR: %s\n", err2); else fprintf(stderr, "ERROR: %s\n", err); fwrite(help_message,1,strlen(help_message),stderr); exit(1); /* return 1; */ /* useless */}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -