Home > Software design >  how to concat int or pid to string in C the way I like it doing
how to concat int or pid to string in C the way I like it doing

Time:01-09

I have these lines that break and throws error at 439 memcpy(&path[0] strlen("ls /proc/"),pid,1);

This is the code

void get_pid()
{
    char line[1000];
    FILE *cmd = popen("pidof a.out", "r");

    fgets(line, 100, cmd);
    pid_t pid = strtoul(line, NULL, 10);
    char *path=malloc(sizeof(char)*100);
    memset(path,0,100);
    memcpy(path,"ls /proc/",strlen("ls /proc/"));
    memcpy(&path[0] strlen("ls /proc/"),pid,1);
    system(path);
    free(path);
    
    return;
}

is there any neat way of accomplish I just to execute ls command the way I am trying it just takes /proc/ and concat with pid I got from system(pidof) Actually I need to get into ls /proc/my_pid=pid/fd/ and find socket fd. there is only one socket file in /proc/pid/fd/ directory

How to do it in C

Actually this line is trouble maker

 memcpy(&path[0] strlen("ls /proc/"),pid,1);

I am just taking the address of first character plusing it with strlen and then write with mcmcpy just 1. But obviously the above is wrong since my second parameter to memcpy is type int which is 4 byte and it expect char pointer which is 8 bytes. Can I cast it may be but I need to do it the correct way in C. Can anyone please help

CodePudding user response:

It is generally recommended to thing of what you are trying to do and what type are the data.

You first use popen to extract the result of the command pidof a.out. fgets will give you a string ending with a newline. Just replace that last character with a null

...
fgets(line, 100, cmd);
line[strlen(line) -1] = '\0';

You later want to concatenate that value to another string... It is useless to convert it to a pid_t only to convert it back to a string (unless you want to control that the format it correct).

Furthermore, the memxxx functions are recommended to process arbitrary character array that could contain null characters. Here you only handle null terminated strings, so you should use the strxxx functions.

Finally unless you want to experiment with it, using dynamic allocation for a fixed size array is non idiomatic... What you want is:

char path[100] = "ls /proc/";

That is enough to get an array of 100 characters initialized with the content of "ls /proc" followed by null characters.

Just concatenate your initial string:

strcat(path, line);
system(path);

Anyway, this is still poor code, because you should never rely on input data and should always test that what you get is what you expected, but I'll keep that for another answer...

CodePudding user response:

There are a number of ways to go about finding the pid of the current process and then getting a directory listing of the process directory -- but you are making it harder than need be.

Most compiles provide the POSIX function getpid() which will retrieve the current process pid. To determine how many characters are needed for the combined "ls /proc/" and pid, just use the old snprinf() trick with the buffer NULL and the number of chars set to 0 and snprintf() will return the length that would be required to hold the completed string, e.g.

  len = snprintf (NULL, 0, "ls /proc/%d", pid);   /* determine len req'd */

With the length, you can allocate len 1 bytes and then use sprintf() to fill the string, e.g.

  if (!(path = malloc (len   1))) {               /* allocate len   1 */
    perror ("malloc-path");
    return;
  }
  
  sprintf (path, "ls /proc/%d", pid);     /* create path */

All that remains is making your system() call. Putting it altogether, you can do:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

void get_pid ()
{
  char *path;
  int len;
  pid_t pid = getpid();     /* get pid of current proc */
  
  len = snprintf (NULL, 0, "ls /proc/%d", pid);   /* determine len req'd */
  if (!(path = malloc (len   1))) {               /* allocate len   1 */
    perror ("malloc-path");
    return;
  }
  
  sprintf (path, "ls /proc/%d", pid);     /* create path */
  
  system (path);    /* list contents of process directory */
  free (path);      /* free path */
}

int main () {
  
  get_pid();
  
}

(note: for your use you can avoid the length checking and dynamic allocations simply be declaring path as a fixed-size array, e.g. char path[128]; would more than suffice, then you can simply call sprintf() and create the desired string)

The version using a fixed-size path simplifies to:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

void get_pid ()
{
  char path[128];           /* fixed buffer to hold final string */
  pid_t pid = getpid();     /* get pid of current proc */
  
  sprintf (path, "ls /proc/%d", pid);     /* create path */
  
  system (path);    /* list contents of process directory */
}

int main () {
  
  get_pid();
  
}

Either way is fine.

Example Use/Output

Running the code does provide a listing of the current process directory, e.g.

$ ./bin/lsprocpid
attr        coredump_filter  fdinfo    make-it-fail  mountstats  oom_score_adj  sched      stat     timerslack_ns
auxv        cpuset           gid_map   map_files     net         pagemap        schedstat  statm    uid_map
cgroup      cwd              io        maps          ns          patch_state    sessionid  status   wchan
clear_refs  environ          latency   mem           numa_maps   personality    setgroups  syscall
cmdline     exe              limits    mountinfo     oom_adj     projid_map     smaps      task
comm        fd               loginuid  mounts        oom_score   root           stack      timers

This is probably one of the more concise ways to approach it. There are many ways with strcat(), etc, but when you need to mix numbers and text in a printf() like format-string, then using sprintf() to create the combined string is about as simple way as you have.

Look things over and let me know if you have further questions.

  •  Tags:  
  • Related