I'm writing a custom shell and I want it to execute a script:
if [ type less > /dev/null ];then PAGER=less; fi
echo $PAGER
printenv|grep $1|$PAGER
It works if I run it from the bash and with my custom shell:
$ ./shell -f ../checkenv.sh GNOME
[13607]
[13606]
GNOME_KEYRING_CONTROL=
GNOME_KEYRING_PID=
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
INSTANCE=GNOME
XDG_CURRENT_DESKTOP=GNOME
(END)
But if I start my shell and then try and run the script, I get an error message.
$ ./shell
'PATH' is set to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin.
$ ../checkenv.sh GNOME
14786: executing ../checkenv.sh
../checkenv.sh: 2: [: type: unexpected operator
14786: executed
$
This seems to be because I don't have a shebang, but I don't know how to use a shebang for a custom shell. Should I install my custom shell in /usr/bin/ or make some other arrangement?
My main function and my readline function are:
int main(int argc, char *argv[]) {
bool donotrun = false;
struct sigaction new_action, old_action;
hashtable_t *hashtable = ht_create(65536);
/* Set up the structure to specify the new action. */
new_action.sa_handler = termination_handler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGINT, &new_action, NULL);
sigaction(SIGHUP, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGHUP, &new_action, NULL);
sigaction(SIGTERM, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction(SIGTERM, &new_action, NULL);
bool background = false;
int index = 0;
int i;
char *cvalue = NULL;
const char *commandFile = NULL;
while (1) {
index = 0;
i = getopt_long(argc, argv, "pc:fvh",
options, &index);
if (i == -1)
break;
switch (i) {
case 'p': {
exit(EXIT_SUCCESS);
}
case 'v': {
printf("sh OpenShell version 0.1(a)\n");
printf("Version: %s\n", VERSION);
// printf ("%s / %s / %s / %s\n",
// program_name, version,
// build_date, build_git_sha);
exit(EXIT_SUCCESS);
}
case 'h': {
usage();
exit(EXIT_SUCCESS);
}
case 'c': {
cvalue = optarg;
command(cvalue, hashtable, background);
exit(EXIT_SUCCESS);
}
case 'f': {
/*
* Execute commands from file.
* This is used for osh script files.
* The quiet flag is also set.
*/
//if ((argc != 1) || commandFile)
//usage();
//quietFlag = TRUE;
printf("case f\n");
//commandFile = *argv++;
argc--;
*argv++;
*argv++;
readFile(*argv++, argc, argv, hashtable, background);
//free(line);
exit(0);
//break;
}
case '?':
if (optopt == 'c')
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf(stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf(stderr,
"Unknown option character `\\x%x'.\n",
optopt);
default: {
return 1;
}
}
}
getPath();
char *copy = "";
for (; ;) {
bool scanning = true;
while (scanning) {
char *line = NULL;
line = readline("$ ");
if (line == NULL) {
/* No more lines, so exit the loop. */
break;
}
if (line)
copy = strdup(line);
if (line && !strstr(line, "for") && !strstr(line, "==") && !strstr(line, "if") && strstr(line, "=")) {
donotrun = true;
char str[128];
char *ptr;
strcpy(str, line);
strtok_r (str, "=", &ptr);
ht_set(hashtable, str, ptr);
}
if (!scanning)
break;
if (commandFile!=NULL || !isatty(fileno(stdin))) {
*argv++;
readFile(*argv++, argc, argv, hashtable, background);
free(line);
exit(0);
}
else {
if (!donotrun) {
line = strrep(line, " | ", "|");
line = strrep(line, " |", "|");
background = testFn2(line);
if (background)
line[strlen(line) - 1] = '\0';
command(line, hashtable, background);
}
donotrun = false;
add_history(copy);
}
free(copy);
}
}
// ParseFree(pParser, free);FIXME: where should this go?
return 0;
}
/*
* Read commands from the specified file.
* A null name pointer indicates to read from stdin.
*/
static int readFile(const char *name, int argc, char ** argv, hashtable_t *hashtable, bool background) {
FILE *fp;
int cc;
bool ttyFlag;
char buf[CMD_LEN];
int r = 0;
if (sourceCount >= MAX_SOURCE) {
fprintf(stderr, "Too many source files\n");
return 1;
}
fp = stdin;
printf("name %s\n", name);
if (name) {
fp = fopen(name, "r");
if (fp == NULL) {
perror(name);
return 1;
}
}
sourcefiles[sourceCount++] = fp;
ttyFlag = isatty(fileno(fp));
int i = 0;
while (true) {
if (ttyFlag)
showPrompt();
if (intFlag && !ttyFlag && (fp != stdin)) {
fclose(fp);
sourceCount--;
return 1;
}
if (fgets(buf, CMD_LEN - 1, fp) == NULL) {
if (ferror(fp) && (errno == EINTR)) {
clearerr(fp);
continue;
}
break;
}
cc = strlen(buf);
if (buf[cc - 1] == '\n')
cc--;
while ((cc > 0) && isBlank(buf[cc - 1]))
cc--;
buf[cc] = '\0';
//printf("buf %s\n", argv[0]);
strreplace(buf, "$1", argv[0]);
//printf("arg %s\n", ++argv);
if (strstr(buf, "=")) {
char str[128];
char *ptr;
strcpy(str, buf);
strtok_r (str, "=", &ptr);
ht_set(hashtable, str, ptr);
}
//printf("the command is %s\n", buf);
r = command(buf, hashtable, background);
i++;
}
if (ferror(fp)) {
perror("Reading command line");
if (fp == stdin)
exit(1);
}
clearerr(fp);
if (fp != stdin)
fclose(fp);
sourceCount--;
return r;
}
A shebang line simply specifies the full path to the interpreter, plus (optionally) an argument to be passed.
Apparently your custom shell requires a -f followed by the script name, followed by any arguments to be passed to the script.
So just add this as the first line of your script:
#!/path/to/shell -f
and make sure the script has execute permissions. Your shell doesn't have to be installed in /usr/bin; you just have to specify the full path on the #! line.
There's also a /usr/bin/env hack:
#!/usr/bin/env shell
but on many systems it doesn't permit passing an extra argument. (You might consider modifying your custom shell so it takes the script name as an argument without the -f.) I've discussed the pros and cons of #!/usr/bin/env in this answer.
Note that the #! mechanism is handled by the kernel, not by the shell.
You might simply remove the square brackets in your script test:
if type less > /dev/null ;then PAGER=less; fi
echo $PAGER
printenv|grep $1|$PAGER
Related
Can anyone tell me what's the issue in this please? I am getting an error that
"grep: c is not a file or directory". If do this same pattern for 1 pipe (2 commands), it works perfectly, However, if I do it with 2 pipes (3 commands), it stops working.
CAN ANYONE PLEASE TELL ME WHAT'S THE ISSUE IN THIS CODE?
int main(int argc, char** argv)
{
int pipefd[2];
int pipefd2[2];
char* cmd[3]={"ls",NULL,NULL};
char* cmd2[3]={"grep","c",NULL};
char* cmd3[3]={"wc", NULL, NULL};
pipe(pipefd);
pipe(pipefd2);
if(fork() == 0)
{
if(dup2(pipefd[1],1) < 0)
{
printf("Error in dup2\n");
exit(0);
}
close(pipefd2[0]);
close(pipefd2[1]);
close(pipefd[0]);
close(pipefd[1]);
if(execvp("ls", cmd) < 0)
{
printf("Error in execvp ls\n");
exit(0);
}
}
if(fork() == 0)
{
if(dup2(pipefd[0],0) < 0)
{
printf("Error in dup2\n");
exit(0);
}
if(dup2(pipefd2[1], 1) < 0)
{
printf("Error in dup2\n");
exit(0);
}
close(pipefd2[0]);
close(pipefd2[1]);
close(pipefd[0]);
close(pipefd[1]);
if(execvp("grep",cmd2) < 0)
{
printf("Error in execvp grep\n");
exit(0);
}
}
if(fork() == 0)
{
if(dup2(pipefd2[0],0) < 0)
{
printf("Error in dup2\n");
exit(0);
}
close(pipefd2[0]);
close(pipefd2[1]);
close(pipefd[0]);
close(pipefd[1]);
if(execvp("wc",cmd2) < 0)
{
printf("Error in execvp wc\n");
exit(0);
}
}
close(pipefd[0]);
close(pipefd[1]);
close(pipefd2[0]);
close(pipefd2[1]);
wait(NULL);
wait(NULL);
wait(NULL);
return 0;
}
This is caused by incorrect use of execvp.
The first argument is the file you wish to execute, and the second argument is an array of null-terminated strings that represent the appropriate arguments to the file.
Effectively, you are running grep grep c in your shell. You can try it, and see that the same effect happens.
See the man page https://linux.die.net/man/3/execvp for further reading.
I would like to implement a main function such as in order to execute system commands. The following code is currently used :
int main(int argc, char *argv[])
{
size_t cmd_length;
char *cmd_buffer = NULL;
char *file = NULL;
char *ip = NULL;
int size;
if(argc == 3)
{
size = strlen(argv[1]);
file = (char*)malloc((size + 1)*sizeof(char));
strcpy(file, argv[1]);
size = strlen(argv[2]);
ip = (char*)malloc((size + 1)*sizeof(char));
strcpy(ip, argv[2]);
}
cmd_length = snprintf(NULL, 0, "tftp -g -r %s %s", file, ip);
cmd_buffer = malloc(cmd_length + 1);
if (cmd_buffer == NULL)
{
return -1;
}
snprintf(cmd_buffer, cmd_length + 1, "tftp -g -r %s %s", file, ip);
if(system(cmd_buffer) == 0)
{
then ...
}
{
return -1;
}
free(cmd_buffer);
cmd_buffer = NULL;
cmd_length = snprintf(NULL, 0, "tftp -g -r %s %s", DFT_FILE, DFT_IP);
cmd_buffer = malloc(cmd_length + 1);
if (cmd_buffer == NULL)
{
return -1;
}
snprintf(cmd_buffer, cmd_length + 1, "tftp -g -r %s %s", DFT_FILE, DFT_IP);
if(system(cmd_buffer) == 0)
{
then ...
}
{
return -1;
}
free(cmd_buffer);
free(file);
free(ip);
cmd_buffer = NULL;
file = NULL;
ip = NULL;
return 0;
}
Because I need to enter other commands, I am currently using the same cmd_buffer by using free() before reallocating memory. Is it the right way to do ? Some other commands might be required in the future.
Your program can be be greatly simplified if you use a common function to execute the system call. It doesn't even need to use malloc at all. Here's a partial implementation [Please pardon the gratuitous style cleanup]:
#include <stdarg.h>
int
execute_command(const char *fmt,...)
{
char cmd_buffer[5000];
int cmd_length;
va_list ap;
// NOTE: much simpler to used a fixed size buffer that is larger than
// needed
va_start(ap,fmt);
cmd_length = vsnprintf(cmd_buffer,sizeof(cmd_buffer),fmt,ap);
va_end(ap);
if (system(cmd_buffer) != 0)
return -1;
return 0;
}
int
main(int argc, char *argv[])
{
char *file = NULL;
char *ip = NULL;
// NOTE: I had to guess the intent if fewer arguments are passed (e.g. just
// skip as I did here, print message and abort?)
if (argc == 3) {
// NOTE: no need to malloc these, but if you did, see strdup(3)
file = argv[1];
ip = argv[2];
execute_command("tftp -g -r %s %s", file, ip);
}
execute_command("tftp -g -r %s %s", DFT_FILE, DFT_IP);
return 0;
}
Yes, you are essentially just re-using the pointer variable cmd_buffer which is fine. And for every malloc() there is a matching free(), which is good.
You should factor our common code into a function, for example runCommand(const char *command, ...) (using varargs).
I'm trying to pipe my h264 stream to ffmpeg and then to my v4l2loopback device. Problem is that I'm fairly new to linux, so just can't get it working.
The stream can be outputted to stdout, but I do not know how to catch it again with ffmpeg and then again pipe it to my v4l2loopback device.
Does anybody know how this could be done or maybe a pointer on how to solve it?
This is the capture program:
PS! You can find the options for the capture program almost in the bottom of the code.
/*
* V4L2 video capture example, modified by Derek Molloy for the Logitech C920 camera
* Modifications, added the -F mode for H264 capture and associated help detail
* www.derekmolloy.ie
*
* V4L2 video capture example
*
* This program can be used and distributed without restrictions.
*
* This program is provided with the V4L2 API
* see http://linuxtv.org/docs.php for more information
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#define CLEAR(x) memset(&(x), 0, sizeof(x))
enum io_method {
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
};
struct buffer {
void *start;
size_t length;
};
static char *dev_name;
static enum io_method io = IO_METHOD_MMAP;
static int fd = -1;
struct buffer *buffers;
static unsigned int n_buffers;
static int out_buf;
static int force_format = 0;
static int frame_count = 100;
static void errno_exit(const char *s)
{
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
exit(EXIT_FAILURE);
}
static int xioctl(int fh, int request, void *arg)
{
int r;
do {
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
static void process_image(const void *p, int size)
{
if (out_buf)
fwrite(p, size, 1, stdout);
fflush(stderr);
fprintf(stderr, ".");
fflush(stdout);
}
static int read_frame(void)
{
struct v4l2_buffer buf;
unsigned int i;
switch (io) {
case IO_METHOD_READ:
if (-1 == read(fd, buffers[0].start, buffers[0].length)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit("read");
}
}
process_image(buffers[0].start, buffers[0].length);
break;
case IO_METHOD_MMAP:
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit("VIDIOC_DQBUF");
}
}
assert(buf.index < n_buffers);
process_image(buffers[buf.index].start, buf.bytesused);
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
break;
case IO_METHOD_USERPTR:
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit("VIDIOC_DQBUF");
}
}
for (i = 0; i < n_buffers; ++i)
if (buf.m.userptr == (unsigned long)buffers[i].start
&& buf.length == buffers[i].length)
break;
assert(i < n_buffers);
process_image((void *)buf.m.userptr, buf.bytesused);
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
break;
}
return 1;
}
static void mainloop(void)
{
unsigned int count;
unsigned int loopIsInfinite = 0;
if (frame_count == 0) loopIsInfinite = 1; //infinite loop
count = frame_count;
while ((count-- > 0) || loopIsInfinite) {
for (;;) {
fd_set fds;
struct timeval tv;
int r;
FD_ZERO(&fds);
FD_SET(fd, &fds);
/* Timeout. */
tv.tv_sec = 2;
tv.tv_usec = 0;
r = select(fd + 1, &fds, NULL, NULL, &tv);
if (-1 == r) {
if (EINTR == errno)
continue;
errno_exit("select");
}
if (0 == r) {
fprintf(stderr, "select timeout\n");
exit(EXIT_FAILURE);
}
if (read_frame())
break;
/* EAGAIN - continue select loop. */
}
}
}
static void stop_capturing(void)
{
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
errno_exit("VIDIOC_STREAMOFF");
break;
}
}
static void start_capturing(void)
{
unsigned int i;
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
errno_exit("VIDIOC_STREAMON");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
buf.index = i;
buf.m.userptr = (unsigned long)buffers[i].start;
buf.length = buffers[i].length;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
errno_exit("VIDIOC_STREAMON");
break;
}
}
static void uninit_device(void)
{
unsigned int i;
switch (io) {
case IO_METHOD_READ:
free(buffers[0].start);
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap(buffers[i].start, buffers[i].length))
errno_exit("munmap");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i)
free(buffers[i].start);
break;
}
free(buffers);
}
static void init_read(unsigned int buffer_size)
{
buffers = calloc(1, sizeof(*buffers));
if (!buffers) {
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
buffers[0].length = buffer_size;
buffers[0].start = malloc(buffer_size);
if (!buffers[0].start) {
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
}
static void init_mmap(void)
{
struct v4l2_requestbuffers req;
CLEAR(req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
fprintf(stderr, "%s does not support "
"memory mapping\n", dev_name);
exit(EXIT_FAILURE);
} else {
errno_exit("VIDIOC_REQBUFS");
}
}
if (req.count < 2) {
fprintf(stderr, "Insufficient buffer memory on %s\n",
dev_name);
exit(EXIT_FAILURE);
}
buffers = calloc(req.count, sizeof(*buffers));
if (!buffers) {
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
errno_exit("VIDIOC_QUERYBUF");
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start =
mmap(NULL /* start anywhere */,
buf.length,
PROT_READ | PROT_WRITE /* required */,
MAP_SHARED /* recommended */,
fd, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start)
errno_exit("mmap");
}
}
static void init_userp(unsigned int buffer_size)
{
struct v4l2_requestbuffers req;
CLEAR(req);
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_USERPTR;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
fprintf(stderr, "%s does not support "
"user pointer i/o\n", dev_name);
exit(EXIT_FAILURE);
} else {
errno_exit("VIDIOC_REQBUFS");
}
}
buffers = calloc(4, sizeof(*buffers));
if (!buffers) {
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
for (n_buffers = 0; n_buffers < 4; ++n_buffers) {
buffers[n_buffers].length = buffer_size;
buffers[n_buffers].start = malloc(buffer_size);
if (!buffers[n_buffers].start) {
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
}
}
static void init_device(void)
{
struct v4l2_capability cap;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_format fmt;
unsigned int min;
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
if (EINVAL == errno) {
fprintf(stderr, "%s is no V4L2 device\n",
dev_name);
exit(EXIT_FAILURE);
} else {
errno_exit("VIDIOC_QUERYCAP");
}
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf(stderr, "%s is no video capture device\n",
dev_name);
exit(EXIT_FAILURE);
}
switch (io) {
case IO_METHOD_READ:
if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
fprintf(stderr, "%s does not support read i/o\n",
dev_name);
exit(EXIT_FAILURE);
}
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
fprintf(stderr, "%s does not support streaming i/o\n",
dev_name);
exit(EXIT_FAILURE);
}
break;
}
/* Select video input, video standard and tune here. */
CLEAR(cropcap);
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap.defrect; /* reset to default */
if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
switch (errno) {
case EINVAL:
/* Cropping not supported. */
break;
default:
/* Errors ignored. */
break;
}
}
} else {
/* Errors ignored. */
}
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fprintf(stderr, "Force Format %d\n", force_format);
if (force_format) {
if (force_format==2){
fmt.fmt.pix.width = 1920;
fmt.fmt.pix.height = 1080;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
}
else if(force_format==1){
fmt.fmt.pix.width = 640;
fmt.fmt.pix.height = 480;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
}
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
errno_exit("VIDIOC_S_FMT");
/* Note VIDIOC_S_FMT may change width and height. */
} else {
/* Preserve original settings as set by v4l2-ctl for example */
if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))
errno_exit("VIDIOC_G_FMT");
}
/* Buggy driver paranoia. */
min = fmt.fmt.pix.width * 2;
if (fmt.fmt.pix.bytesperline < min)
fmt.fmt.pix.bytesperline = min;
min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
if (fmt.fmt.pix.sizeimage < min)
fmt.fmt.pix.sizeimage = min;
switch (io) {
case IO_METHOD_READ:
init_read(fmt.fmt.pix.sizeimage);
break;
case IO_METHOD_MMAP:
init_mmap();
break;
case IO_METHOD_USERPTR:
init_userp(fmt.fmt.pix.sizeimage);
break;
}
}
static void close_device(void)
{
if (-1 == close(fd))
errno_exit("close");
fd = -1;
}
static void open_device(void)
{
struct stat st;
if (-1 == stat(dev_name, &st)) {
fprintf(stderr, "Cannot identify '%s': %d, %s\n",
dev_name, errno, strerror(errno));
exit(EXIT_FAILURE);
}
if (!S_ISCHR(st.st_mode)) {
fprintf(stderr, "%s is no device\n", dev_name);
exit(EXIT_FAILURE);
}
fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
if (-1 == fd) {
fprintf(stderr, "Cannot open '%s': %d, %s\n",
dev_name, errno, strerror(errno));
exit(EXIT_FAILURE);
}
}
static void usage(FILE *fp, int argc, char **argv)
{
fprintf(fp,
"Usage: %s [options]\n\n"
"Version 1.3\n"
"Options:\n"
"-d | --device name Video device name [%s]\n"
"-h | --help Print this message\n"
"-m | --mmap Use memory mapped buffers [default]\n"
"-r | --read Use read() calls\n"
"-u | --userp Use application allocated buffers\n"
"-o | --output Outputs stream to stdout\n"
"-f | --format Force format to 640x480 YUYV\n"
"-F | --formatH264 Force format to 1920x1080 H264\n"
"-c | --count Number of frames to grab [%i] - use 0 for infinite\n"
"\n"
"Example usage: capture -F -o -c 300 > output.raw\n"
"Captures 300 frames of H264 at 1920x1080 - use raw2mpg4 script to convert to mpg4\n",
argv[0], dev_name, frame_count);
}
static const char short_options[] = "d:hmruofFc:";
static const struct option
long_options[] = {
{ "device", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "mmap", no_argument, NULL, 'm' },
{ "read", no_argument, NULL, 'r' },
{ "userp", no_argument, NULL, 'u' },
{ "output", no_argument, NULL, 'o' },
{ "format", no_argument, NULL, 'f' },
{ "formatH264", no_argument, NULL, 'F' },
{ "count", required_argument, NULL, 'c' },
{ 0, 0, 0, 0 }
};
int main(int argc, char **argv)
{
dev_name = "/dev/video0";
for (;;) {
int idx;
int c;
c = getopt_long(argc, argv,
short_options, long_options, &idx);
if (-1 == c)
break;
switch (c) {
case 0: /* getopt_long() flag */
break;
case 'd':
dev_name = optarg;
break;
case 'h':
usage(stdout, argc, argv);
exit(EXIT_SUCCESS);
case 'm':
io = IO_METHOD_MMAP;
break;
case 'r':
io = IO_METHOD_READ;
break;
case 'u':
io = IO_METHOD_USERPTR;
break;
case 'o':
out_buf++;
break;
case 'f':
force_format=1;
break;
case 'F':
force_format=2;
break;
case 'c':
errno = 0;
frame_count = strtol(optarg, NULL, 0);
if (errno)
errno_exit(optarg);
break;
default:
usage(stderr, argc, argv);
exit(EXIT_FAILURE);
}
}
open_device();
init_device();
start_capturing();
mainloop();
stop_capturing();
uninit_device();
close_device();
fprintf(stderr, "\n");
return 0;
}
It's a modified version of a V4L2 video capture example.
Then I know that if I have outputed the streame to a file I would have to run this command to convert the raw format to mp4 format:
ffmpeg -f h264 -i output.raw -vcodec copy output.mp4
And the v4l2loopback program I'm using is foud here:
https://github.com/umlaeute/v4l2loopback
------------------Update------------------
Okay. So I got the pipe from the capture program to ffmpeg working. It captures, decodes the h264 and I can write it to a mp4 file with this command:
./capture -F -d /dev/video0 -o | ffmpeg -f h264 -i - -vcodec copy out.mp4
Now I am trying to get the last pipe working with this command:
./capture -F -d /dev/video0 -o | ffmpeg -f h264 -i - -vcodec copy -f mp4 - | gst-launch-0.10 -v fdsrc ! v4l2sink device=/dev/video3
I get these errors:
muxer does not support non seekable output
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Any ideas?
In your last command you are piping an MP4 to GStreamer. See the -f mp4 - part:
./capture -F -d /dev/video0 -o | ffmpeg -f h264 -i - -vcodec copy -f mp4 - | gst-launch-0.10 -v fdsrc ! v4l2sink device=/dev/video3
What you want to do is pipe the H.264 stream inside the MP4 instead.
Try replacing -f mp4 - with -f h264 -.
In fact you could probably skip entirely the creation of an MP4 and just do:
./capture -F -d /dev/video0 -o | gst-launch-0.10 -v fdsrc ! v4l2sink device=/dev/video3
since the -F option forces H.264.
I am running code in a coding site and got following error:
solution: malloc.c:2369: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted (core dumped)
Code:
#include <stdio.h>
#include <string.h>
#include <math.h>
typedef struct cell
{
int x;
int y;
struct cell *prevcell;
struct cell *nextcell;
}cell;
/* Head ends here */
void nextMove(int x, int y, int pacman_x, int pacman_y, int food_x, int food_y, char grid[x][y]){
//logic here
int i=pacman_x;
int j=pacman_y;
cell *top,*node;
top = NULL;
while(grid[i][j] != '.')
{
node = NULL;
//UP
if(i != 0 && grid[i-1][j] != '%')
{
if(grid[i][j] != 'd')
{
printf("%d %d\n",i,j);
grid[i][j]='d';
}
//push
node = (cell*)malloc(sizeof(node));
node->x=i;
node->y=j;
node->prevcell=top;
node->nextcell=NULL;
if(top != NULL)
top->nextcell=node;
top=node;
i=i-1;
}
//LEFT
else if(j != 0 && grid[i][j-1] != '%')
{
if(grid[i][j] != 'd')
{
printf("%d %d\n",i,j);
grid[i][j]='d';
}
//push
node = (cell*)malloc(sizeof(node));
node->x=i;
node->y=j;
node->prevcell=top;
node->nextcell=NULL;
if(top != NULL)
top->nextcell=node;
top=node;
j=j-1;
}
//RIGHT
else if(j != y-1 && grid[i][j+1] != '%')
{
if(grid[i][j] != 'd')
{
printf("%d %d\n",i,j);
grid[i][j]='d';
}
//push
node = (cell*)malloc(sizeof(node));
node->x=i;
node->y=j;
node->prevcell=top;
node->nextcell=NULL;
if(top != NULL)
top->nextcell=node;
top=node;
j=j+1;
}
//DOWN
else if(i != x-1 && grid[i+1][j] != '%')
{
if(grid[i][j] != 'd')
{
printf("%d %d\n",i,j);
grid[i][j]='d';
}
//push
node = (cell*)malloc(sizeof(node));
node->x=i;
node->y=j;
node->prevcell=top;
node->nextcell=NULL;
if(top != NULL)
top->nextcell=node;
top=node;
i=i+1;
}
else
{
//pop
top=top->prevcell;
free(top->nextcell);
i=top->x;
j=top->y;
}
}
}
/* Tail starts here */
int main() {
int x, y;
int pacman_x, pacman_y;
int food_x, food_y;
scanf( "%d %d", &pacman_x, &pacman_y);
scanf( "%d %d", &food_x, &food_y);
scanf( "%d %d", &x, &y);
char grid[x][y];
for( int i=0; i<x; i++) {
scanf("%s[^\\n]%*c", grid[i]);
}
nextMove( x, y, pacman_x, pacman_y, food_x, food_y, grid);
return 0;
}
I am not getting the issue. Could someone help??
Your scanf() format is wrong.
scanf("%s[^\\n]%*c", grid[i]);
This is saying to scanf() for
1) a string (%s)
2) the character '['
3) the character '^'
4) the character '\'
5) the character 'n'
6) the character ']'
7) a char (%*c), but do not store it
You might want to drop the 's'
scanf("%[^\\n]%*c", grid[i]);
Idea:
char buf[80];
fgets(buf, sizeof(buf)-1, stdin);
sscanf(buf, "%[^\\n]", grid[i]);
I find it safer to separate Input from parsing.
Further, you have
char grid[x][y];
This appears to be a dynamically allocation of "grid" based on the size of x & y. This is not C (unless it a new feature). So I need to ask, what compiler are you using?
Ohh.. I got the issue.
The following malloc call is incorrect:
node = (cell*)malloc(sizeof(node));
It will allocate only 4 bytes (node being a pointer).
The correct version would be:
node = (cell*)malloc(sizeof(*node));
OR
node = (cell*)malloc(sizeof(cell));
How silly of me..!!
I am working on an application that will trigger a UAC prompt in whatever program is opened by ShellExecute.
I can't figure out how to hard-code a path for the ShellExecute to run. As of now this program uses whatever path is in arg[0]. How can I build a string to put in the place of arg[0] on the line sinfo.lpFile = arg[0];?
I am very new so if you can't see why making a string to put in that line will solve my problem then you are most likely right.
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <shellapi.h>
#include <process.h>
#include "uac-example.h"
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst,LPSTR cmdLine, int nCmdShow){
LPWSTR *arg;
int argc = 0;
HRESULT ret = SUCCESS;
WCHAR imagePath[MAXPATHLEN];
WCHAR workingDir[MAXPATHLEN];
WCHAR uacDir[MAXPATHLEN];
WCHAR uacRunningLockFilePath[MAXPATHLEN];
HANDLE uacRunningLockFileHandle = INVALID_HANDLE_VALUE;
WCHAR elevatedLockFilePath[MAXPATHLEN];
HANDLE elevatedLockFileHandle = INVALID_HANDLE_VALUE;
arg = CommandLineToArgvW(GetCommandLineW(),&argc);
//if(arg == NULL || argc < 2) {
// ERRORBOX("Missing required program arguments.\n\nUsage:\nuac-example.exe <working directory>");
// return FAILURE;
//}
GetModuleFileName(NULL, imagePath, MAXPATHLEN);
arg[0] = imagePath;
wcscpy_s((wchar_t *)uacDir, MAXPATHLEN, arg[1]);
_snwprintf_s(uacRunningLockFilePath, MAXPATHLEN, MAXPATHLEN,
_T("%s/") _T(RUNNING_LOCK_FILE), uacDir);
wcscpy_s(workingDir, MAXPATHLEN, imagePath);
WCHAR *slash = wcsrchr(workingDir, '\\');
wcscpy_s(slash, MAXPATHLEN, _T(""));
_snwprintf_s(elevatedLockFilePath, MAXPATHLEN, MAXPATHLEN,_T("%s/") _T(ELEVATE_LOCK_FILE), workingDir);
uacRunningLockFileHandle = CreateFileW(uacRunningLockFilePath,(GENERIC_READ | GENERIC_WRITE),0,NULL,OPEN_ALWAYS,FILE_FLAG_DELETE _ON_CLOSE,NULL);
if (uacRunningLockFileHandle == INVALID_HANDLE_VALUE) {
if (_waccess(elevatedLockFilePath, F_OK) == 0 &&
_wremove(elevatedLockFilePath) != 0) {
return FAILURE;
}
elevatedLockFileHandle = CreateFileW(elevatedLockFilePath,(GENERIC_READ | GENERIC_WRITE),0,NULL,OPEN_ALWAYS,FILE_FLAG_DELETE _ON_CLOSE,NULL);
if(elevatedLockFileHandle == INVALID_HANDLE_VALUE){
ERRORBOX("Unable to acquire the necessary permissions to run demo app.");
return FAILURE;
}
LPWSTR spawnCmdLine = BuildCommandLine(argc - 1, arg + 1);
if(!spawnCmdLine){
CloseHandle(elevatedLockFileHandle);
ERRORBOX("An error occured while respawning self.");
return FAILURE;
}
SHELLEXECUTEINFO sinfo;
memset(&sinfo, 0, sizeof(SHELLEXECUTEINFO));
sinfo.cbSize = sizeof(SHELLEXECUTEINFO);
sinfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS;
sinfo.hwnd = NULL;
sinfo.lpFile = arg[0];
sinfo.lpParameters = spawnCmdLine;
sinfo.lpVerb = L"runas"; // <<-- this is what makes a UAC prompt show up
sinfo.nShow = SW_SHOWMAXIMIZED;
BOOL result = ShellExecuteEx(&sinfo);
LocalFree(spawnCmdLine);
if(result){
WaitForSingleObject(sinfo.hProcess, INFINITE);
CloseHandle(sinfo.hProcess);
return SUCCESS;
}else{
return FAILURE;
}
}
EXIT_IF_ELEVATED(elevatedLockFilePath,uacRunningLo ckFileHandle,SUCCESS);
LocalFree(arg);
return SUCCESS;
}
// ----------------------------------------------------------------------
// The following code was taken directly from the Mozilla Firefox Updater
// source tree, and slightly modified to support "Wide" strings in
// Visual C++.
// ----------------------------------------------------------------------
LPWSTR
BuildCommandLine(int argc, LPWSTR *argv){
int i;
int len = 0;
// The + 1 of the last argument handles the
// allocation for null termination
for (i = 0; i < argc; ++i) {
len += ArgStrLen(argv[i]) + 1;
}
// Protect against callers that pass 0 arguments
if (len == 0) {
len = 1;
}
LPWSTR s = (LPWSTR)malloc(len * sizeof(LPWSTR));
if (!s) {
return NULL;
}
LPWSTR c = s;
for (i = 0; i < argc; ++i) {
c = ArgToString(c, argv[i]);
if (i + 1 != argc) {
*c = ' ';
++c;
}
}
*c = '\0';
return s;
}
int
ArgStrLen(LPWSTR s) {
int backslashes = 0;
int i = wcslen(s);
BOOL hasDoubleQuote = wcschr(s, L'"') != NULL;
// Only add doublequotes if the string contains a space or a tab
BOOL addDoubleQuotes = wcspbrk(s, L" \t") != NULL;
if (addDoubleQuotes) {
i += 2; // initial and final duoblequote
}
if (hasDoubleQuote) {
while (*s) {
if (*s == '\\') {
++backslashes;
} else {
if (*s == '"') {
// Escape the doublequote and all backslashes preceding the doublequote
i += backslashes + 1;
}
backslashes = 0;
}
++s;
}
}
return i;
}
LPWSTR
ArgToString(LPWSTR d, LPWSTR s) {
int backslashes = 0;
BOOL hasDoubleQuote = wcschr(s, L'"') != NULL;
// Only add doublequotes if the string contains a space or a tab
BOOL addDoubleQuotes = wcspbrk(s, L" \t") != NULL;
if (addDoubleQuotes) {
*d = '"'; // initial doublequote
++d;
}
if (hasDoubleQuote) {
int i;
while (*s) {
if (*s == '\\') {
++backslashes;
} else {
if (*s == '"') {
// Escape the doublequote and all backslashes\
// preceding the doublequote
for (i = 0; i <= backslashes; ++i) {
*d = '\\';
++d;
}
}
backslashes = 0;
}
*d = *s;
++d; ++s;
}
} else {
wcscpy(d, s);
d += wcslen(s);
}
if (addDoubleQuotes) {
*d = '"'; // final doublequote
++d;
}
return d;
}
Simply as:
char path[] = "C:\\program.exe";
sinfo.lpFile = path;